Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Symbol-keyed Hooks
// ⚠️ This is NOT the React Hooks API
const key = Symbol();
function Form() {
// ...
const name = useFormInput(key, "name");
const surname = useFormInput(key, "surname");
// ...
return (
<>
<input {...name} />
<input {...surname} />
{/* ... */}
</>
)
}
/*******************
* useFormInput.js *
******************/
const keys = new WeakMap();
function useFormInput(key, name) {
if(!keys.has(key)){
keys.set(key, {[name]: Symbol(name)});
} else if(!Object.keys(keys.get(key)).includes(name)){
keys.get(key)[name] = Symbol(name);
}
const [value, setValue] = useState(keys.get(key)[name]);
return {
name
value,
onChange(e) {
setValue(e.target.value);
},
};
}
// Assumes that useWindowWidth() and useNetworkStatus() are only used once per component.
function StatusMessage() {
const width = useWindowWidth();
const isOnline = useNetworkStatus();
return (
<>
<p>Window width is {width}</p>
<p>You are {isOnline ? 'online' : 'offline'}</p>
</>
);
}
const subscriptionKeys = new WeakMap();
function useSubscription(key, subscribe, unsubscribe, getValue) {
if(!subscriptionKeys.has(key)){
subscriptionKeys.set(key, {state: Symbol(), effect: Symbol()});
}
const [state, setState] = useState(subscriptionKeys.get(key).state, getValue());
useEffect(subscriptionKeys.get(key).effect, () => {
const handleChange = () => setState(getValue());
subscribe(handleChange);
return () => unsubscribe(handleChange);
});
return state;
}
const windowWidthKey = Symbol();
function useWindowWidth() {
const width = useSubscription(windowWidthKey,
handler => window.addEventListener('resize', handler),
handler => window.removeEventListener('resize', handler),
() => window.innerWidth
);
return width;
}
const networkStatusKey = Symbol();
function useNetworkStatus() {
const isOnline = useSubscription(networkStatusKey,
handler => {
window.addEventListener('online', handler);
window.addEventListener('offline', handler);
},
handler => {
window.removeEventListener('online', handler);
window.removeEventListener('offline', handler);
},
() => navigator.onLine
);
return isOnline;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment