Реагировать с использованием хуков и контекста без повторного рендеринга компонента, который использует только функцию установки - PullRequest
0 голосов
/ 06 августа 2020

Я использую в своем проекте перехватчики реакции. Я пытаюсь предотвратить повторную визуализацию сложной кнопки / интерфейса, где я хочу открыть модальное окно справки. Однако эту кнопку необходимо использовать во всем приложении, не вызывая повторной визуализации. Есть ли способ использовать установщик без принудительного обновления этого несвязанного компонента?

Вот самый упрощенный пример кода, который я мог сгенерировать. Это поставщик контекста:

// Provider.js
export default function ModalProvider(props: React.PropsWithChildren<{}>) {
  // adding the event state info
  const [helpModalOpen, setHelpModalOpen] = useState(false as any);
  
  const contextValue = {
    helpModalOpen,
    setHelpModalOpen,
  };

  return (
    <StateContext.Provider value={{...contextValue}}>
      {props.children}
    </StateContext.Provider>
  );
}

export function useModalState() {
  const context = useContext(StateContext);
  if (!context) {
    throw new Error('useModalState must be used within the AppStateProvider');
  }
  return context;
}

И это очень сложный компонент, который нельзя разбить (это видеоинтерфейс):

// ComplexButtonToOpenHelpModal.js
export default function ComplexComponent() {
   const {setHelpModalOpen} = useModalState();
   return (
       <ExtremelyComplexComponent onClick={setHelpModalOpen}  />
   );
}

Хотя это простой пример, мне нужно использовать аналогичный код во всем этом приложении.

1 Ответ

0 голосов
/ 06 августа 2020

Одним из возможных простых решений было бы разделить ваш контекст на две части:

// Provider.js
const ModalOpenContext = React.createContext();
const SetModalOpenContext = React.createContext();

export default function ModalProvider(props: React.PropsWithChildren<{}>) {
  // adding the event state info
  const [helpModalOpen, setHelpModalOpen] = useState(false as any);

  return (
    <SetModalOpenContext.Provider value={setHelpModalOpen}>
      <ModalOpenContext.Provider value={helpModalOpen}>
        {props.children}
      </ModalOpenContext.Provider>
    </SetModalOpenContext.Provider>
  );
}

export function useModalState() {
  const context = useContext(ModalOpenContext);
  if (!context) {
    throw new Error('useModalState must be used within the AppStateProvider');
  }
  return context;
}

export function useSetModalState() {
  const context = useContext(SetModalOpenContext);
  if (!context) {
    throw new Error('useSetModalState must be used within the AppStateProvider');
  }
  return context;
}
// ComplexButtonToOpenHelpModal.js
export default function ComplexComponent() {
   const setHelpModalOpen = useSetModalState();
   return (
       <ExtremelyComplexComponent onClick={setHelpModalOpen}  />
   );
}

Теперь вы передаете стабильное значение своему SetModalOpenContext.Provider, поэтому компоненты, которые подписываются на него использование useSetModalState никогда не будет принудительно выполнено повторно, поскольку значение не изменится со временем.

Как вы отметили в своем вопросе, документы React указывают , что: «Все потребители которые являются потомками Провайдера, будут повторно визуализироваться всякий раз, когда изменяется свойство значения Провайдера. ". 1) разделить контекст на отдельные части (как показано выше) или 2) использовать какой-либо другой механизм для передачи необходимых данных по вашему приложению.

...