将上下文拆分为状态并更新以提高性能(减少渲染)?

mle*_*ter 3 reactjs react-hooks use-context

一些博客文章在使用React Context时将上下文分为两个单独的更新和状态上下文。我想知道这是否真的提高了性能或可以减少渲染周期。

所以最终的解决方案将是:

  • 两个不同的上下文对象
  • 两个不同的钩子用于1.) 访问状态2.) 修改状态
  • 两个独立的提供者(包装成一个单独的提供者,如AuthProvider

拆分更新状态上下文的解决方案:

const authContext = React.createContext<AuthUser | null | undefined>(undefined)
const authUpdateContext = React.createContext<Dispatch<SetStateAction<AuthUser | null>> | null>(null)

export function useAuth() {
    const authUser = React.useContext(authContext);
    if (authUser === undefined) throw new Error(`useAuth must be used within a ContextAuthProvider`);
    return authUser;
}

export const useAuthUpdate = () => {
    const setAuthUser = React.useContext(authUpdateContext);
    if (!setAuthUser) throw new Error(`useAuthUpdate must be used within a AuthProvider`);
    return setAuthuser;
}

export const AuthProvider: React.FC = ({children}) => {
    const [authUser, setAuthUser] = useState<AuthUser | null>(null)
    return (
        <authUpdateContext.Provider value={setAuthUser}>
            <authContext.Provider value={authUser}>
                {children}
            </authContext.Provider>
        </authUpdateContext.Provider>
    )
}

// Usage only in components where needed (one of those two or both combined)
const authUpdate = useAuthUpdate()
const auth = useAuth()
Run Code Online (Sandbox Code Playgroud)

pil*_*ard 5

上下文的操作往往不会改变,而这些操作控制的状态却会改变。如果您创建一个同时提供状态值和状态更新方法的上下文,则每次状态值更改时,订阅该上下文的所有组件都会触发渲染,即使它们只访问操作(可能没有更改) 。

您可以避免这种情况,并通过将上下文拆分为两个单独的上下文(如示例中所示),在仅订阅操作上下文的组件上保存渲染(以及相关的副作用,例如 useEffect() 调用)。

这是一个相关的问题:Avoid runnning an Effect hook when Context get update清楚地说明了这一点。如果该示例中仅使用一个上下文,则 ActionsComponent 中的 useEffect 会在 ValueComponent 中计数器的每一次滴答时触发,但事实并非如此,因为每个组件都订阅不同的上下文。

以下是 React 存储库上的问题中选项的简要概述: 使用 React.memo 和 useContext 钩子防止重新渲染。#15156:选项 1(首选):拆分不会一起更改的上下文