React Context всегда будет перерисовывать - PullRequest
0 голосов
/ 11 марта 2020

Если вы объявляете объект в значении контекста Provider, любые потребители контекста всегда будут перерисовывать, если провайдер повторно рендерит, потому что каждый раз, когда провайдер повторно рендерит объект внутри value, объявляется повторно.

return (
  <Provider value={{ /* declared object */ }}>{children}</Provider>
);

Хороший поставщик value Шаблон

Ниже приведен хороший шаблон, поскольку store изменится только при вызове setStore.

// ParentComponent.js

function ParentComponent() {
  const [store, setStore] = useState({ bool: false });

  return (
    <Context.Provider value={store}>
      <button onClick={() => setStore({ ...store, n: { bool: !store.n.bool } })}>
        Switch Bool
      </button>
      <ContextConsumingComponent />
    </Context.Provider>
  );
}

// ContextConsumingComponent.js
function ContextConsumingComponent() {
  const store = useContext(Context);

  console.log('Will only run re-render if the `Switch Bool` button is clicked in parent.');

  return <p>{JSON.stringify(context.bool)}</p>;
}
// Avoid re-renders if props haven't changed.
export default React.memo(ContextConsumingComponent);

Плохой поставщик value Pattern

Это плохой шаблон, потому что <Provider value={{}} /> прослушивает изменения для включающего объекта, а не сами ссылки store и setStore. Реальность такова, что мы все равно хотим действительно слушать store.

// ParentComponent.js

function ParentComponent() {
  const [store, setStore] = useState({ bool: false });


  return (
    <Context.Provider value={{ store, setStore }}>
      <button onClick={() => setStore({ ...store, n: { bool: !store.n.bool } })}>
        Switch Bool
      </button>
      <ContextConsumingComponent />
    </Context.Provider>
  );
}

Вопрос:

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

Опция двух провайдеров: store и dispatch

// Two Providers
function ParentComponent() {
  const [store, setStore] = useState({ bool: false });


  return (
    <Store.Provider value={store}>
      <Dispatch.Provider value={setStore}>
        <button onClick={() => setStore({ ...store, n: { bool: !store.n.bool } })}>
          Switch Bool
        </button>
        <ContextConsumingComponent />
      </Dispatch.Provider>
    </Store.Provider>
  );
}

1 Ответ

0 голосов
/ 11 марта 2020

Ответ на мой вопрос скорее всего useMemo.

function App() {
  const [store, setStore] = useState({ bool: false });

  const memoized = useMemo(() => ([store, setStore]), [store, setStore]);


  return (
    <RCTX.Provider value={memoized}>
        <button onClick={() => setStore({ bool: !store.bool })}>
            Switch Bool
        </button>
        <SubComponent />
    </RCTX.Provider>
  );
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...