Created
December 13, 2018 14:02
-
-
Save thomasfoster96/c4a20053c747196f027fcd871fc82f03 to your computer and use it in GitHub Desktop.
Symbol-keyed Hooks
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ⚠️ 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); | |
}, | |
}; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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