传递的对象每次渲染都会改变

Object passed changes every render

我正在尝试为我正在使用 React 构建的应用程序定义一个全局状态提供程序。但我一直收到错误

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

这是我的文件结构。 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,
}

我已经多次查看代码,但似乎无法弄清楚哪里出了问题以及为什么会出现此错误。 如果有人可以进一步解释为什么会发生这种情况以及可能会有所帮助的解决方案。

这并不是真正的语法错误,这意味着它不会破坏应用程序,而是一个 linting 错误,一些 linter 试图执行最佳标准。您可以更改 linter 设置以提供警告而不是抛出错误。

如果你想解决这个问题,你可以按照 linter 的建议将上下文值包装在 useMemo 挂钩中。

const globalContextValue = useMemo(
    () => ({
      dispatch, globalState
    }),
    [dispatch, globalState]
  );

    return (
        <GlobalContext.Provider value={globalContextValue}>
            {children}
        </GlobalContext.Provider>
    )

请注意,围绕此 linting 规则存在争议,有人说它已过时且不必要,因此有人建议完全禁用该规则。