Является ли проблема размещения React Context Provider и использования тех, кто использует useContext, проблемой? - PullRequest
2 голосов
/ 17 марта 2019

С какой проблемой я могу столкнуться с глубоко вложенным провайдером контекста 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 Ответ

4 голосов
/ 17 марта 2019

Наличие вложенных контекстов не вызовет проблем в вашем коде.В вышеприведенном случае, если вы подпишетесь на 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 в codeSandbox здесь

PS Однако вы должны убедиться, что вы не создаете новый объект при прохождениизначение для провайдера, в противном случае каждый раз, когда провайдер переопределяет все дочерние элементы, которые подписываются на его контекст, переопределяется

...