Last active
July 30, 2022 12:30
-
-
Save raphtlw/f4a7c3ebdd622f562139400a66916e4c to your computer and use it in GitHub Desktop.
Inline functional context builder
This file contains hidden or 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
import { | |
useContext, | |
createContext, | |
type ReactNode, | |
type Provider as ReactProvider, | |
} from 'react' | |
/** | |
* Utility context builder which streamlines the context | |
* building and exposing API. | |
* | |
* @param displayName | |
* Display name which is shown in React DevTools | |
* (default: 'Context') | |
* @param ProviderWrapper | |
* Context's provider wrapper which provides the context provider | |
* | |
* @returns [Context's provider (Provider), | |
* Context's consumer (useContext), | |
* Utility HOC (withProvider)] | |
*/ | |
export const buildContext = < | |
TContext extends {}, | |
ProviderWrapperProps extends {} | |
>( | |
displayName: string = 'Context', | |
ProviderWrapper: React.FC< | |
{ | |
children: ReactNode | |
Root: ReactProvider<TContext | null> | |
} & ProviderWrapperProps | |
> | |
) => { | |
const Context = createContext<TContext | null>(null) | |
Context.displayName = displayName | |
const Consumer = (): TContext => { | |
const context = useContext(Context) | |
if (!context) { | |
throw new Error( | |
`use${displayName} can only be used inside ${displayName}Provider` | |
) | |
} | |
return context | |
} | |
const Provider: React.FC<{ children: ReactNode } & ProviderWrapperProps> = ({ | |
children, | |
...props | |
}) => ( | |
<ProviderWrapper Root={Context.Provider} {...props}> | |
{children} | |
</ProviderWrapper> | |
) | |
const withProvider = (props: ProviderWrapperProps) => { | |
const providerWrapper = (Component: React.FC) => ( | |
<Provider {...props}> | |
<Component /> | |
</Provider> | |
) | |
return providerWrapper | |
} | |
return [Provider, Consumer, withProvider] as const | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Usage