Use createStateContext to share a useState hook
Despite so many folks touting React's useContext as a state management solution, it really doesn't have anything to do with state management at all.
React Context is about dependency injection. You provide a value to a wrapper component, and then any downstream component can use that value via a useContext hook.
Most of the time I use Context I also want to provide a way to update the value from the child components. I like the useState API, but it needs to be shareable
I've built a helper function called createStateContext
that takes the same types as useState and returns a tuple of the Context and a hook to use it.
Consider a CheckboxGroup component, which needs to keep track of which checkboxes are checked.
const [CheckboxContext, useCheckboxContext] = createStateContext<string[]>()// optional for better error messagesCheckboxContext.displayName = "CheckboxContext"function CheckboxGroup({ children }) { const state = useState<string[]>([]) return ( <CheckboxContext.Provider value={state}> {children} </CheckboxContext.Provider> )}
Any child component can use the useCheckboxContext
hook to get a state and setState function that is shared with all its siblings.
const [checkboxes, setCheckboxes] = useCheckboxContext()
<CheckboxGroup> <Checkbox value="foo" /> <Checkbox value="bar" /> <Checkbox value="baz" /></CheckboxGroup>
The hook
import React, { useContext } from "react"export function createStateContext<T>() { const StateContext = React.createContext< | undefined | Readonly<[T, React.Dispatch<React.SetStateAction<T>>]> >(undefined) function useStateContext() { const tuple = useContext(StateContext) if (tuple === undefined) { throw new Error( `use${StateContext.displayName} must be used within a ${StateContext.displayName}Provider`, ) } return tuple } return [StateContext, useStateContext] as const}