React Context and Hook
15th April, 2023
Although I use this all the time I always have to look up how to implement it. This example is based on Kent C. Dodds' article on the subject.
import * as React from 'react'type Action = {type: 'increment'} | {type: 'decrement'}type Dispatch = (action: Action) => voidtype State = {count: number}type CountProviderProps = {children: React.ReactNode}const CountStateContext = React.createContext<{state: State; dispatch: Dispatch} | undefined>(undefined)function countReducer(state: State, action: Action) {switch (action.type) {case 'increment': {return {count: state.count + 1}}default: {throw new Error(`Unhandled action type: ${action.type}`)}}}function CountProvider({children}: CountProviderProps) {const [state, dispatch] = React.useReducer(countReducer, {count: 0})// NOTE: you *might* need to memoize this value// Learn more in http://kcd.im/optimize-contextconst value = {state, dispatch}return (<CountStateContext.Provider value={value}>{children}</CountStateContext.Provider>)}function useCount() {const context = React.useContext(CountStateContext)if (context === undefined) {throw new Error('useCount must be used within a CountProvider')}return context}export {CountProvider, useCount}
The provider can then be used like so:
<CountProvider><ChildComponents /></CountProvider>
And in our components that need the context:
const {state, dispatch} = useCount();