Created
November 18, 2018 19:23
-
-
Save mvolkmann/1c5df4124b1d11866fd5dc91969f22a7 to your computer and use it in GitHub Desktop.
a custom React hook named "useTopState" that is similar to "useState", but allows multiple components to share the state and be rerendered when it changes
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
const stateMap = {}; | |
function render(state) { | |
for (const component of state.components) component.forceUpdate(); | |
} | |
export default function useTopState(name, initialValue) { | |
let state = stateMap[name]; | |
if (!state) { | |
const updater = { | |
delete() { | |
this.value = undefined; | |
render(state); | |
}, | |
set(value) { | |
this.value = value; | |
render(state); | |
}, | |
transform(fn) { | |
this.value = fn(this.value); | |
render(state); | |
} | |
}; | |
if (typeof initialValue === 'number') { | |
updater.decrement = () => { | |
this.value--; | |
render(state); | |
}; | |
updater.increment = () => { | |
this.value++; | |
render(state); | |
}; | |
} else if (Array.isArray(initialValue)) { | |
updater.filter = fn => { | |
this.value = this.value.filter(fn); | |
render(state); | |
}; | |
updater.map = fn => { | |
this.value = this.value.map(fn); | |
render(state); | |
}; | |
updater.push = (...newValues) => { | |
this.value.push(...newValues); | |
render(state); | |
}; | |
} | |
state = {components: new Set(), updater, value: initialValue}; | |
stateMap[name] = state; | |
} | |
//TODO: Get reference to the component that called this! | |
const component = 'HOW CAN I GET THIS?'; | |
state.components.add(component); | |
return [state.value, state.updater]; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
A function component can use it like this: