I recently enterd a project and saw something that I have not seen before when it comes to useContext in react.
The global state in the project uses hooks which it sends in to a context and then when calling that hook later on the global state is accesable. The problem I saw with this is that ther is no defined global state in one place, you can create a hook with state and update functions, send it in to a provider and get access to it anywhere in the project..
Code:
const initialState = {
id: "MyId",
currency: 'currency',
};
function useCurrencyState() {
initialState.currency = 'newCurrency'
const [currency, setCurrency] = React.useState(initialState);
return {
currency
};
}
export const [useCurrency, CurrencyStoreProvider] = createStoreProvider(useCurrencyState);
The provider:
export function createStoreProvider(useHook) {
const [useContextConsumer, ContextProvider] = generateContext();
const StoreProvider = ({ children }) => {
const state = useHook();
return <ContextProvider value={state}>{children}</ContextProvider>;
};
return [useContextConsumer, StoreProvider];
}
generate context func:
export function generateContext() {
const context = React.createContext(undefined);
const useContextConsumer = () => {
const c = React.useContext(context);
if (!c) {
throw new Error('Component must be wrapped with <Container.Provider>');
}
return c;
};
return [useContextConsumer, context.Provider];
}
the store:
const StoreProvider = ({ children }) => (
<CurrencyStoreProvider>
{children}
</CurrencyStoreProvider>
);
export default StoreProvider;
and when you want to use the useCurrency you would
import { useCurrency } from 'store/currency';
const { currency} = useCurrency ();
The above example is for one hook. The project has 4 of them which follow the same pattern and the project has 4 nested providers/contexts.
My inital thought to this is that it is mutating state anonymously since it doesnt have a global defined state and no reducer who catches the action in order to update the global state.
Am I right? Is this the not so recommended way to handle state? If im worng what is this pattern called if it has a name?
I was about to recommend to change to using a context + useReducer with action and dispatch but I need to get a better understanding of the above.
EDIT:
For clarity: The provders are nested like this:
const StoreProvider = ({ children }) => (
<CurrencyProvider>
<UserStoreProvider>
<CartStoreProvider>
<NotificationsStoreProvider>
{children}
</NotificationsStoreProvider>
</CartStoreProvider>
</UserStoreProvider>
</CurrencyProvider>
);
As im sceptic to this approach, would it be more efficent to have ONE context and have useReducer/Redux to manage state updates?.
I guess that above example(Edit section) is done to prevent rerendering on state update which maybe makes sense if you dont use a reducer.