嵌套React Context Provider并使用useContext消耗那些问题吗?

Ben*_*LLE 3 reactjs react-hooks

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

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

并使用像这样的上下文依赖来消费那些嵌套提供程序:

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 };
Run Code Online (Sandbox Code Playgroud)

这个上下文依赖关系是否总是“重新触发”菜单上下文提供程序?=>特别是关于无用的重新渲染?

Shu*_*tri 5

嵌套上下文不会在您的代码中引起任何问题。在上述情况下,如果您订阅UserContextin MenuContextMenuContext则仅当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);
Run Code Online (Sandbox Code Playgroud)

您可以在此处的代码沙箱中看到一个DEMO

PS但是,您必须确保在将值传递给Provider时未创建新对象,否则,每次Provider重新渲染所有订阅其上下文的子级时,都会重新渲染

  • 那是因为没有人订阅 ThemeProvider,如果有任何组件订阅,它会在 ThemeProvider 重新渲染时重新渲染 (2认同)