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

时间:2019-03-17 09:07:01

标签: reactjs react-hooks

深度嵌套的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 };

此上下文相关性是否总是“重新触发”菜单上下文提供程序? =>特别是关于无用的重新渲染?

1 个答案:

答案 0 :(得分:4)

具有嵌套上下文不会在您的代码中引起任何问题。在上述情况下,如果您在UserContext中订阅了MenuContext,则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

  

PS 。但是,您必须确保没有创建新对象   同时将值传递给提供者,否则每次提供者   重新渲染所有订阅其上下文的孩子,将重新渲染