react-singleton-hook + use-context-selector
I have a utilty function that creates a Context.Provider, and a useContext.
For my specific case, I'd like to use use-context-selector library to improve the performance of my application.
The API for the use-context-selector is: const myContextData = useContextSelector(Context, (state) => state[0].data);
In my function, I create an abstraction for the useContextSelector, like this: (contextSelectorFn) => useContextSelector(Context, contextSelectorFn).
This way, I can use my custom hook directly like: const myUserId = useUserData((state) => state[0].id);.
I'm sort of having a hard time understand how could I simply adhere to this singleton pattern for this use case.
Here's the code for my utility function as of now:
import type { Dispatch, ReactElement, ReactNode, SetStateAction } from 'react';
import { useState } from 'react';
import { createContext, useContextSelector } from 'use-context-selector';
type GlobalState<State> = [State, Dispatch<SetStateAction<State>>];
type Provider = (props: { children: ReactNode }) => ReactElement;
type GlobalContext<State> = <Selected>(
selector: (value: GlobalState<State>) => Selected,
) => Selected;
function createGlobalStateContext<State>(
initialState: State,
): [GlobalContext<State>, Provider] {
const Context = createContext<GlobalState<State>>([initialState, () => {}]);
const ProviderComponent: Provider = ({ children }) => {
const [state, setState] = useState<State>(initialState);
const contextState: GlobalState<State> = [state, setState];
return <Context.Provider value={contextState}>{children}</Context.Provider>;
};
return [
(contextSelectorFn) => useContextSelector(Context, contextSelectorFn),
ProviderComponent,
];
}
Hi @rnarcos, underlying state change always causes a component to rerender. I'll take a look at the library you are using and try to incorporate something similar when have time.
I've actually thought about another kind of optimization, used by swr: you can just
const { id } = useUserData();
and the component will only update when id has changed, not any other field. will this work for you?