I am trying to define a global state provider for an app I am building with react. But I keep getting the error
The object passed as the value prop to the Context provider (at line 19) changes every render. To fix this consider wrapping it in a useMemo hook
Here is my file structure. state.ts
export default interface State {
data: boolean
}
export const initialState: State = {
data: false,
}
action.ts
type Action = {
type: "SET_DATA"
value: boolean
}
export default Action
context.ts
import { Context, createContext, Dispatch } from "react"
import Action from "./actions"
import State, { initialState } from "./state"
const GlobalContext: Context<{
globalState: State
dispatch: Dispatch<Action>
// eslint-disable-next-line @typescript-eslint/no-unused-vars
}> = createContext({ globalState: initialState, dispatch: (_: Action) => {} })
export default GlobalContext
provider.tsx
import * as React from "react"
import { ReactNode, ReactElement, useReducer } from "react"
import GlobalContext from "./context"
import Reducer from "./reducer"
import State, { initialState as defaultInitialState } from "./state"
export default function GlobalStateProvider({
children,
initialState = defaultInitialState,
}: {
children: ReactNode
initialState?: State
}): ReactElement {
const [globalState, dispatch] = useReducer(Reducer, initialState)
return (
<GlobalContext.Provider value={{ dispatch, globalState }}>
{children}
</GlobalContext.Provider>
)
}
GlobalStateProvider.defaultProps = {
initialState: defaultInitialState,
}
I have gone through the code multiple times and I cannot seem to figure out what is wrong and why I am getting this error. If someone can further explain why this is happening and perhaps and solution that would be helpful.
This is not really a syntax error, meaning it won't break the app, but a linting error, where some linters are trying to enforce best standards. You can change linter settings to provide warnings instead of throwing errors.
If you want to fix this, you can wrap the context values in a useMemo hook as the linter suggested.
const globalContextValue = useMemo(
() => ({
dispatch, globalState
}),
[dispatch, globalState]
);
return (
<GlobalContext.Provider value={globalContextValue}>
{children}
</GlobalContext.Provider>
)
Note that there are controversies around this linting rule, some say that its outdated and unnecessary, so some would suggest to disable the rule entirely.