嵌套 React Context Provider 并使用 useContext 消费它们有问题吗?

Is nesting React Context Provider and consuming those with useContext a problem?

深度嵌套的 React 上下文提供程序会遇到什么问题?

const AllContextProvider = props => {
  return (
    <UserProvider>
      <ThemeProvider>
        <NotifProvider>
          <TimelineProvider>
            <CertProvider>
              <MenusProvider>
              {props.children}
              </MenusProvider>
            </CertProvider>
          </TimelineProvider>
        </NotifProvider>
      </ThemeProvider>
    </UserProvider>
  );
};

并像这样使用具有上下文依赖性的嵌套提供程序:

import React, { useContext } from "react";
import { UserContext } from "./UserContext";
import { useLocalStoragePerUser } from "./useLocalStoragePerUser";

const MenusContext = React.createContext();
const { Provider } = MenusContext;

const MenusProvider = props => {
  // Is this context dependencie always "re-trigger" the Menu Context Provider?
  const { user } = useContext(UserContext);

  // Menus Context
  const [menu, setMenu] = useLocalStoragePerUser( "menus", {
      icons: false,
      labels: true,
      leftMenu: true,
    },
    user
  );

  return (
    <Provider value={{ menu, setMenu}} >
      {props.children}
    </Provider>
  );
};

export { MenusProvider, MenusContext };

这个上下文依赖总是"re-trigger"菜单上下文提供者吗? => 特别是关于无用的重新渲染?

嵌套上下文不会在您的代码中造成任何问题。在上述情况下,如果您在 MenuContext 中订阅 UserContext,则 MenuContext 只会在 UserContext 更改提供给其提供者的值时重新呈现。但是,除非 MenuContext 更改它传递给 MenuContext Provider 的值,否则订阅 MenuContext 的子项将不会重新呈现,也不会重新呈现其他子项

import React from "react";
import ReactDOM from "react-dom";
import { UserProvider } from "./UserProvider";
import { ThemeProvider } from "./ThemeProvider";
import { MenusProvider } from "./MenuProvider";

import "./styles.css";
function Child() {
  console.log("Child render");
  return <div>Menus Child</div>;
}
function App() {
  return (
    <div className="App">
      <h1>Hello CodeSandbox</h1>
      <h2>Start editing to see some magic happen!</h2>
      <UserProvider>
        <ThemeProvider>
          <MenusProvider>
            <Child />
          </MenusProvider>
        </ThemeProvider>
      </UserProvider>
    </div>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

你可以看到一个DEMO in the codeSandbox here

P.S. However you must make sure that you are not creating a new object while passing the value to a Provider otherwise everytime the Provider re-renders all children which subscribe to its context will re-render