### Install signal-utils and signal-polyfill Source: https://github.com/proposal-signals/signal-utils/blob/main/README.md Installs the necessary packages for using signal-utils and its polyfill. This command adds both 'signal-utils' and 'signal-polyfill' to your project's dependencies. ```bash npm add signal-utils signal-polyfill ``` -------------------------------- ### Install Dependencies with pnpm Source: https://github.com/proposal-signals/signal-utils/blob/main/CONTRIBUTING.md Installs all necessary project dependencies using the pnpm package manager. This is a prerequisite for developing and testing the project. ```bash pnpm install ``` -------------------------------- ### Start Build and Tests in Watch Mode with concurrently Source: https://github.com/proposal-signals/signal-utils/blob/main/CONTRIBUTING.md Initiates a concurrent build process using pnpm start, which runs both the Vite build and Vitest tests in parallel. This is useful for debugging the build process or preparing for releases. ```bash pnpm start ``` -------------------------------- ### JavaScript localCopy for Two-Way Binding Source: https://github.com/proposal-signals/signal-utils/blob/main/README.md Demonstrates using the `localCopy` function to create a mutable local signal that mirrors a read-only remote signal. It includes an example of updating the local signal from an input event, suitable for controlled input elements. ```javascript import { Signal } from 'signal-polyfill'; import { localCopy } from 'signal-utils/local-copy'; const remote = new Signal.State(3); const local = localCopy(() => remote.get()); const updateLocal = (inputEvent) => local.set(inputEvent.target.value); // A controlled input ``` -------------------------------- ### Run Vitest Tests in Watch Mode Source: https://github.com/proposal-signals/signal-utils/blob/main/CONTRIBUTING.md Starts the Vitest test runner in watch mode, automatically re-running tests when source files change. This is the primary method for developing and unit testing within the package. ```bash pnpm vitest --watch ``` -------------------------------- ### Create signals with @signal decorator Source: https://github.com/proposal-signals/signal-utils/blob/main/README.md Demonstrates the use of the '@signal' decorator to create reactive signals within a class. It shows how to define a signal accessor and a computed property that depends on it, along with a method to update the signal's value. This example is suitable for frameworks like Glimmer or Svelte. ```jsx import { signal } from 'signal-utils'; class State { @signal accessor #value = 3; get doubled() { return this.#value * 2; } increment = () => this.#value++; } let state = new State(); // output: 6 // button clicked // output: 8 ``` -------------------------------- ### Deep reactivity with @deepSignal decorator Source: https://github.com/proposal-signals/signal-utils/blob/main/README.md Shows how to use the '@deepSignal' decorator for recursive, deep, and lazy auto-tracking of JSON-serializable structures. This allows for reactivity at any depth within objects and arrays. The example demonstrates updating nested properties and incrementing a value within a deeply nested structure. ```gjs import { deepSignal } from 'signal-utils/deep'; class Foo { @deepSignal accessor obj = {}; } let instance = new Foo(); let setData = () => instance.obj.foo = { bar: 3 }; let inc = () => instance.obj.foo.bar++; {{instance.obj.foo.bar}} ``` -------------------------------- ### Cache getters with @signal decorator Source: https://github.com/proposal-signals/signal-utils/blob/main/README.md Illustrates using the '@signal' decorator to cache the results of a getter method within a class. This is useful for expensive computations, especially when returning non-primitive values to maintain referential integrity. The example shows a 'doubled' getter that is cached. ```js import { signal } from 'signal-utils'; class State { @signal accessor #value = 3; // NOTE: read-only because there is no setter, and a setter is not allowed. @signal get doubled() { // imagine an expensive operation return this.#value * 2; } increment = () => this.#value++; } let state = new State(); // output: 6 // button clicked // output: 8 ``` -------------------------------- ### Build the Package Source: https://github.com/proposal-signals/signal-utils/blob/main/CONTRIBUTING.md Executes the build process for the package using the pnpm build command. This is a required step before preparing a Pull Request to ensure the package is correctly built. ```bash pnpm build ``` -------------------------------- ### Construct Reactive Object with SignalObject.fromEntries and signalObject (JSX) Source: https://github.com/proposal-signals/signal-utils/blob/main/README.md Demonstrates alternative ways to construct reactive objects using SignalObject.fromEntries and the signalObject factory function, offering different initialization patterns. ```jsx import { SignalObject, signalObject } from 'signal-utils/object'; SignalObject.fromEntries([ /* ... */ ]); signalObject({ /* ... */ } ); ``` -------------------------------- ### Simplified Reactive Promise Handling with load utility (JavaScript) Source: https://github.com/proposal-signals/signal-utils/blob/main/README.md Shows a more concise way to handle reactive Promises using the `load` utility function from `signal-utils/async-data`. This function simplifies the creation of SignalAsyncData instances. ```js import { load } from 'signal-utils/async-data'; const response = fetch('...'); const signalResponse = load(response); // output: true // after the fetch finishes // output: false ``` -------------------------------- ### Create and Manipulate Reactive Map with SignalMap (JavaScript) Source: https://github.com/proposal-signals/signal-utils/blob/main/README.md Illustrates the creation and usage of a reactive Map with SignalMap. This allows for reactive key-value storage, where changes to map entries trigger updates. ```js import { SignalMap } from 'signal-utils/map'; let map = new SignalMap(); map.set('isLoading', true); // output: true // button clicked // output: false ``` -------------------------------- ### Run All Tests with pnpm test Source: https://github.com/proposal-signals/signal-utils/blob/main/CONTRIBUTING.md Executes all project tests using the pnpm test command. This ensures that all tests pass before preparing a Pull Request. ```bash pnpm test ``` -------------------------------- ### Construct Reactive Array with SignalArray.from and signalArray (JSX) Source: https://github.com/proposal-signals/signal-utils/blob/main/README.md Illustrates alternative methods for creating reactive arrays using SignalArray.from and the signalArray factory function. These methods provide flexibility in initializing SignalArray instances. ```jsx import { SignalArray, signalArray } from 'signal-utils/array'; SignalArray.from([1, 2, 3]); signalArray([1, 2, 3]); ``` -------------------------------- ### Format Code with pnpm format Source: https://github.com/proposal-signals/signal-utils/blob/main/CONTRIBUTING.md Runs the code formatting tool to ensure consistent code style across the project. This command must be executed successfully before submitting a Pull Request. ```bash pnpm format ``` -------------------------------- ### Create and Manipulate Reactive Set with SignalSet (JavaScript) Source: https://github.com/proposal-signals/signal-utils/blob/main/README.md Shows how to create and use a reactive Set with SignalSet. This allows for reactive storage of unique values, where adding or deleting elements triggers updates. ```js import { SignalSet } from 'signal-utils/set'; let set = new SignalSet(); set.add(123); // output: true // button clicked // output: false ``` -------------------------------- ### Create and Manipulate Reactive Object with SignalObject (JavaScript) Source: https://github.com/proposal-signals/signal-utils/blob/main/README.md Shows how to create a reactive object using SignalObject. This is useful for managing object properties reactively, where changes to properties automatically update the UI. ```js import { SignalObject } from 'signal-utils/object'; let obj = new SignalObject({ isLoading: true, error: null, result: null, }); // output: true // button clicked // output: false ``` -------------------------------- ### Create and Manipulate Reactive WeakMap with SignalWeakMap (JavaScript) Source: https://github.com/proposal-signals/signal-utils/blob/main/README.md Demonstrates creating a reactive WeakMap using SignalWeakMap. This provides a reactive way to store key-value pairs where keys are weakly held, suitable for scenarios where memory management is a concern. ```js import { SignalWeakMap } from 'signal-utils/weak-map'; let map = new SignalWeakMap(); let obj = { greeting: 'hello' }; map.set(obj, true); // output: true // button clicked // output: false ``` -------------------------------- ### Create and Manipulate Reactive Array with SignalArray (JSX) Source: https://github.com/proposal-signals/signal-utils/blob/main/README.md Demonstrates creating a reactive array using SignalArray in JSX. It shows how to initialize, render array elements, and modify the array using methods like pop, which trigger UI updates. ```jsx import { SignalArray } from 'signal-utils/array'; let arr = new SignalArray([1, 2, 3]); // output: 3 // button clicked // output: 2 ``` -------------------------------- ### Handle Reactive Promises with SignalAsyncData (JavaScript) Source: https://github.com/proposal-signals/signal-utils/blob/main/README.md Demonstrates using SignalAsyncData to manage the state of a Promise reactively. It provides properties like isLoading, error, and value to track the promise's lifecycle and update the UI accordingly. ```js import { SignalAsyncData } from 'signal-utils/async-data'; const response = fetch('...'); const signalResponse = new SignalAsyncData(response); // output: true // after the fetch finishes // output: false ``` -------------------------------- ### JavaScript localCopy for Two-Way Binding (Preact) Source: https://github.com/proposal-signals/signal-utils/blob/main/README.md An implementation of `localCopy` using Preact hooks, enabling synchronization between a local state and a remote signal. It handles updates from input events and demonstrates parent-child communication for data binding. ```javascript import { render } from 'preact'; import { useRef, useEffect } from 'preact/hooks'; import { signal, effect, useSignal } from '@preact/signals'; import { html } from 'html/preact'; function useLocalCopy(remote) { const local = useRef(); if (!local.current) { local.current = signal(remote.peek()); } useEffect(() => { // Synchronously update the local copy when remote changes. // Core effects are just a way to have synchronous callbacks // react to signal changes in a pretty efficient way. return effect(() => { local.current.value = remote.value; }); }, [remote]); return local.current; } function Demo({ name, onSubmit }) { const localName = useLocalCopy(name); const updateLocalName = (inputEvent) => localName.value = inputEvent.target.value; const handleSubmit = (submitEvent) => { submitEvent.preventDefault(); onSubmit({ value: localName.value }); } return html`
localValue: ${localName}
parent value: ${name}`
}
export function App() {
const name = useSignal('Mace Windu');
const data = useSignal('');
const handleSubmit = (d) => data.value = d;
const changeName = () => name.value += '!';
return html`
<${Demo} name=${name} onSubmit=${handleSubmit} />
${JSON.stringify(data.value, null, 3)}`
}
render(