使用挂钩和上下文进行反应,而无需重新渲染仅使用组件的组件,则使用setter函数

时间:2020-08-06 17:39:26

标签: reactjs react-hooks

我在我的项目中使用了react hooks。我试图防止在要打开帮助模式的地方重新渲染复杂的按钮/界面。但是,此按钮需要在整个应用程序中使用,而不会引起折旧。有没有一种方法可以使用setter而不强制更新不相关的组件?

这是我可以生成的最简化的代码示例。 这是上下文的提供者:

// 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 :(得分:0)

一种可能的简单解决方案是将您的上下文分为两部分:

// 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订阅该值的组件将永远不会被强制重新渲染,因为该值不会随着时间变化。

正如您在问题中所指出的,the React docs point out指出:“只要提供商的价值支柱发生变化,作为提供商的后代的所有使用者都将重新呈现。”

因此,实际上,当您知道上下文值的某个部分将发生变化时,防止重新渲染的唯一方法是:1)将上下文拆分为单独的部分(如上所示)或2)使用其他机制在您的应用中传递必要的数据。