When the React team implemented Context API, developers started to have a better way to pass data through the components. I love to use many local contexts to wrap some parts of the app and have shared data without props chaos.
This is how we can automate React.Context creation, by passing in it our custom hook function:
import * as React from 'react';
type Hook<T, P> = (props: P) => T;
type ContextHook<T> = () => T;
type Provider<P> = React.FunctionComponent<P>;
type CreateContextHookReturn<T, P> = [Provider<P>, ContextHook<T>];
export function createContextHook<T = unknown, P = unknown>(
useHook: Hook<T, P>,
args: { name: string }
): CreateContextHookReturn<T, P> {
const Context = React.createContext<T | undefined>(undefined);
function useContextHook(): T {
const context = React.useContext(Context);
if (context === undefined) {
throw new Error(
`${args.name} Context value is undefined. Make sure you use the ${args.name} Provider before using the context.`
);
}
return context!;
}
function Provider(props: React.PropsWithChildren<P>) {
const value = useHook(props);
return <Context.Provider value={value}>{props.children}</Context.Provider>;
}
return [Provider, useContextHook];
}
Then create your hook and pass it to the createContextHook:
import React from 'react';
import { createContextHook } from '../createContextHook';
// 1. Create your custom hook
type UseMyCustomHookProps = {
someInitialValue: number;
}
function useMyCustomeHook(props: UseMyCustomeHookProps) {
const [count, setCount] = React.useState(props.someInitialValue);
return { count, setCount };
}
// 2. Create and get the Context Hook and Provider
Wrapped your application tree to the provider.
const [MyCustomHookProvider, useMyCustomHookContext] = createContextHook<
// the return value of the hook
ReturnType<typeof useMyHook>,
// the hook input parameter
UseMyHookProps
>(
// Pass your hook reference
useMyCustomHook,
{
// `name` is used only for debugging propose when you failed to connect the hook
name: "MyCustomeHook"
}
);
export { MyHookProvider, useMyHookContext };
Or use npm package:
import { createContextHook } from '@straw-hat/react-hooks';
Top comments (1)
Big fan of dynamic/flexible object creation! Will have to dig in to this more but great concept!! 👍