Skip to content

Instantly share code, notes, and snippets.

@MehYam
Created August 26, 2024 17:38
Show Gist options
  • Save MehYam/9031d618a11691c84a078fa2b3ce37ab to your computer and use it in GitHub Desktop.
Save MehYam/9031d618a11691c84a078fa2b3ce37ab to your computer and use it in GitHub Desktop.
A React managed state solution in 27 lines of code using useSyncExternalStore and no external dependencies
import * as React from 'react';
const events = new EventTarget();
type StateInstance<T> = {
subscribe: (callback: () => void) => (() => void),
getSnapshot: () => T,
setter: (t: T) => void,
data: T
}
const store: Record<string, StateInstance<any>> = {};
function useManagedState<T>(key: string, defaultValue: T) {
if (!store[key]) {
// initialize a state instance for this key
store[key] = {
subscribe: (callback: () => void) => {
events.addEventListener(key, callback);
return () => events.removeEventListener(key, callback);
},
getSnapshot: () => store[key].data,
setter: (t: T) => {
store[key].data = t;
events.dispatchEvent(new Event(key));
},
data: defaultValue
};
}
const instance = store[key] as StateInstance<T>;
const data = React.useSyncExternalStore(instance.subscribe, instance.getSnapshot);
return [data, instance.setter] as const;
}
@MehYam
Copy link
Author

MehYam commented Aug 26, 2024

Sample usage:

let parentRenders = 0;
function ParentComponent() {
    return <div style={{ border: '1px solid red', background: 'gray', padding: 10 }}>
        Parent renders: {++parentRenders}
        <LeafComponentA />
        <LeafComponentB />
    </div>;
}

let leafARenders = 0;
function LeafComponentA() {
    const [state, setState] = useManagedState('test', 0);
    return <div style={{ border: '1px solid gray', background: 'green', padding: 10 }}>
        <div>Leaf Component A</div>
        <div>renders: {++leafARenders}</div>
        <div>state: {state}</div>
        <button onClick={() => setState(state + 1)}>Mutate from A</button>
    </div>
}
let leafBRenders = 0;
function LeafComponentB() {
    const [state, setState] = useManagedState('test', 0);
    return <div style={{ border: '1px solid gray', background: 'blue', padding: 10 }}>
        <div>Leaf Component B</div>
        <div>renders: {++leafBRenders}</div>
        <div>state: {state}</div>
        <button onClick={() => setState(state + 1)}>Mutate from B</button>
    </div>
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment