如何减少反应上下文地狱?

spi*_*ers 9 javascript reactjs react-context react-state-management

我继承了前任所有者广泛使用 React.Context 的代码库。这导致了可能被描述为“上下文地狱”的情况

<AppContextProvider>
  <AnotherProvider>
    <AgainAnotherProvider configProp={false}>
      <TestProvider>
        <FooProvider>
          <BarProvider configHereAlso={someEnvronmentVar}>
            <BazProvider>
              <BatProvider>
                <App />
              </BatProvider>
            </BazProvider>
          </BarProvider>
        </FooProvider>
      </TestProvider>
    </AgainAnotherProvider>
  </AnotherProvider>
</AppContextProvider>;
Run Code Online (Sandbox Code Playgroud)

这感觉像是一种反模式,并且在理解整个应用程序的工作方式方面造成了相当大的认知开销。

我该如何解决?是否可以只使用一个提供程序来处理所有事情?我之前使用 redux-toolkit 和 redux 来管理 React 中的状态。上下文有没有类似的东西?

小智 6

我找到了一个优雅的解决方案

const Providers = ({providers, children}) => {
  const renderProvider = (providers, children) => {
    const [provider, ...restProviders] = providers;
    
    if (provider) {
      return React.cloneElement(
        provider,
        null,
        renderProvider(restProviders, children)
      )
    }

    return children;
  }

  return renderProvider(providers, children)
}

ReactDOM.render(
  <Providers providers={[
    <FooContext.Provider value="foo" />,
    <BarContext.Provider value="bar" />,
    <BazContext.Provider value="baz" />,
  ]}>
    <App />
  </Providers>,
  document.getElementById('root')
);
Run Code Online (Sandbox Code Playgroud)


Ram*_*ddy 2

摆脱额外上下文的一种方法是向上下文提供的值添加更多变量。

例如,如果有两个上下文UserContext并且ProfileContext提供者如下:

<UserContext.Provider value={user}...

<ProfileContext.Provider value={profile}...

然后你可以将它们合并到一个上下文中:

<UserProfileContext.Provider value={{user, profile}}...

注意:这并不意味着您应该将所有上下文合并到单个上下文中,因为当上下文的值更改导致不需要的渲染时,关注点是分离的,并且所有使用者都会重新渲染。

  • 另外,请记住,只有当该值必须在许多地方和/或树的深处使用时,才应使用上下文。否则,只需将值作为属性传递。 (5认同)