предотвратить повторный рендеринг дочернего компонента ниже поставщика контекста с помощью памятки

Я использую поставщик контекста в React для обмена данными между несколькими компонентами. Однако, поскольку значение изменяется от одного из моих подкомпонентов, он повторно отображает все мои другие компоненты, что частично приводит к проблемам с производительностью. Поэтому я хочу предотвратить повторную визуализацию моих дочерних компонентов. Я пробовал использовать React.memo (), но он все еще отображается всякий раз, когда я устанавливаю состояние поставщика контекста.

const Authenticator = React.memo(() => {
  
  const [myChat, setMyChat] = useContext(ChatContext);

  console.log("rerender"); // gets called everytime on click
  return (
    <Button
      title="click me"
      onPress={() => setMyChat({ text: "hello" })}
    ></Button>
  );
});

Мой поставщик контекста выглядит так:

const ChatProvider = ({ children }) => {
  const [myChat, setMyChat] = useState([]);

  return (
    <ChatContext.Provider value={[myChat, setMyChat]}>
      {children}
    </ChatContext.Provider>
  );
};

Мой App.js выглядит так:

<ChatProvider>
  <Authenticator />
</ChatProvider>

person André    schedule 05.01.2021    source источник


Ответы (1)


React.Memo не помогает, так как вы вызываете ловушку useContext, которая заставляет компонент повторно отображать каждый раз, когда значение от поставщика изменяется. Вам следует рассмотреть возможность разделения вашего контекста на два отдельных контекста: один для значения, другой для средства обновления состояния.

const ChatProvider = ({ children }) => {
  const [myChat, setMyChat] = useState([])

  return (
    <ChatDispatchContext.Provider value={setMyChat}>
      <ChatValueContext.Provider value={myChat}>
        {children}
      </ChatValueContext.Provider>
    </ChatDispatchContext.Provider>
  )
}

Затем обновите компонент Authenticator до следующего:

const Authenticator = React.memo(() => {
  const setMyChat = useContext(ChatDispatchContext)

  return (
    <Button
      title="click me"
      onPress={() => setMyChat({ text: "hello" })}
    ></Button>
  )
})
person Mark Skelton    schedule 05.01.2021
comment
Спасибо за ваш ответ. Я все еще не уверен на 100%, что понял, потому что 1) как я могу установить свое состояние с помощью Dispatch Provider в моем ValueContext? 2) поскольку поставщик диспетчеризации находится выше поставщика значений, он также будет повторно отображать дочерние элементы? Жестяная банка - person André; 05.01.2021
comment
1. Вызов setMyChat обновит значение состояния в ChatProvider, которое будет передано вашим компонентам, потребляющим ChatDispatchContext. 2. Порядок провайдеров не имеет значения. Важно то, что ваш Authenticator компонент использует значение контекста, которое не изменяется (setMyChat). Это в сочетании с React.memo предотвратит повторный рендеринг компонента. - person Mark Skelton; 05.01.2021
comment
Является ли разделение на два контекста единственным способом @MarkSkelton? Нет возможности поместить их в один и тот же Провайдер? Пытался обернуть методы контекста с помощью useCallback, но безуспешно. - person Jeaf Gilbert; 26.04.2021