-
Notifications
You must be signed in to change notification settings - Fork 262
/
Copy pathcreateStateProvider.tsx
29 lines (26 loc) · 1.19 KB
/
createStateProvider.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import React from 'react'
import { createContext, useContextSelector } from 'use-context-selector'
type Selector<State> = <T>(selector: (state: State) => T) => T
/**
* This creates a "state provider" component from a getter function.
* The function passed is a getter function to return the value for the state
* provider's context.
*
* @param getState the function to return the context value (state)
* @returns The context provider component and a useStateSelector hook to select context state
*/
export function createStateProvider<State>(getState: () => State): [React.FunctionComponent<{ children: React.ReactNode }>, Selector<State>] {
const Context = createContext<State | undefined>(undefined)
function WithContext({ children }: { children: React.ReactNode }) {
const value = getState()
return <Context.Provider value={value}>{children}</Context.Provider>
}
function useStateSelector<T>(selector: (state: State) => T): T {
const state = useContextSelector(Context, state => {
if (state == null) throw new Error(`Cannot call useStateSelector outside of ${Context.displayName}`)
return selector(state)
})
return state
}
return [WithContext, useStateSelector]
}