Skip to content

Instantly share code, notes, and snippets.

@itsMapleLeaf
Created June 2, 2019 19:48
Show Gist options
  • Save itsMapleLeaf/8ceb9ea146a9de8d2efa40f6a903642b to your computer and use it in GitHub Desktop.
Save itsMapleLeaf/8ceb9ea146a9de8d2efa40f6a903642b to your computer and use it in GitHub Desktop.
createContextWrapper
const missingValue = Symbol()
function createContextWrapper<R, I extends object>(hook: (init: I) => R) {
const Context = React.createContext<R | typeof missingValue>(missingValue)
function Provider(props: I & { children: React.ReactNode }) {
const context = hook(props)
return <Context.Provider value={context}>{props.children}</Context.Provider>
}
function useWrappedContext() {
const context = useContext(Context)
if (context === missingValue) {
throw new Error("Missing context provider")
}
return context
}
return [Provider, useWrappedContext] as const
}
export default createContextWrapper
function useCounterState(props: { initialCount: number }) {
const [count, setCount] = useState(props.initialCount)
return {
count,
increment: () => setCount((c) => c + 1),
decrement: () => setCount((c) => c - 1),
}
}
const [CounterProvider, useCounter] = createContextWrapper(useCounterState)
function Counter() {
const counter = useCounter()
return (
<>
<p>{counter.count}</p>
<button onClick={counter.increment}>+</button>
<button onClick={counter.decrement}>-</button>
</>
)
}
function App() {
return (
<CounterProvider initialCount={0}>
<Counter />
<Counter />
<Counter />
</CounterProvider>
)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment