Created
August 12, 2021 23:20
-
-
Save circAssimilate/0b7b90ee62f224e20384c6d0e3f88509 to your computer and use it in GitHub Desktop.
Context Utils With Use Selectors
This file contains 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
/* eslint-disable @typescript-eslint/no-explicit-any */ | |
import { | |
Context, | |
createContext, | |
useContextSelector, | |
} from '@fluentui/react-context-selector'; | |
type CreateNamedContextReturn<T> = [ | |
Provider: React.Provider<T>, | |
useContext: <V = T>() => V, | |
useContextSelector: <S extends (context: T) => any>( | |
selector: S | |
) => ReturnType<S>, | |
useContextSelector: <S extends keyof T>(keys: Array<keyof T>) => Pick<T, S> | |
]; | |
/** | |
* Function that creates a react context, hook and selector and | |
* will trigger re-render if only the selected value (via selector) | |
* is referentially changed. | |
* | |
* @example | |
* const [PathProvider, usePath, usePathSelector] = createNamedContext() | |
* | |
* // 1 - Use the provider | |
* <PathProvider value={path}> | |
* {children} | |
* </PathProvider> | |
* | |
* // 2 - Read specific parts of the path for render performance | |
* const highlightId = usePathSelector(path => path.highlightId) | |
* | |
* @see Docs https://www.npmjs.com/package/@fluentui/react-context-selector | |
*/ | |
export function createNamedContext<T>( | |
name: string | |
): CreateNamedContextReturn<T> { | |
const context = createContext<T | undefined>(undefined) as Context<T>; | |
context.displayName = name; | |
const useNamedContext = <V = T>() => | |
(useContextSelector(context, (ctx) => ctx) as unknown) as V; | |
const useSelector = <S extends (context: T) => any>( | |
selector: S | |
): ReturnType<S> => | |
useContextSelector((context as unknown) as Context<T>, selector); | |
const useSelectors = <S extends keyof T>( | |
keys: Array<keyof T> | |
): Pick<T, S> => { | |
return keys.reduce<Pick<T, S>>( | |
(acc, key) => ({ | |
...acc, | |
[key]: useSelector((s) => s[key]), | |
}), | |
{} as any | |
); | |
}; | |
return [context.Provider, useNamedContext, useSelector, useSelectors]; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment