首页 > 解决方案 > 如何防止每次导入自定义钩子时调用 customHook 中的 useEffect?

问题描述

我正在使用 react js 和 socket.io 库编写聊天应用程序。

我从服务器订阅事件并发出一些事件的所有逻辑都写在自定义钩子的 useEffect 中。

然后我从这个自定义钩子返回我需要的所有数据,并在我需要的组件中重用它。但是,我意识到每次将此自定义钩子导入外部组件时都会调用用 useEffect 编写的逻辑。

如果我将所有逻辑放在 useEffect 之外,它的调用次数甚至比导入自定义钩子的次数还要多。

如果可能的话,我该如何预防?

如果不可能,请您建议什么解决方案?我不想为这个应用程序使用 redux,我想把所有东西都保存在这个自定义钩子组件中,并在我需要的地方重用它的数据。

我不能分享工作示例,因为没有服务器部分它就无法工作,所以这里是一个简单的代码框示例。您可以在控制台中看到它被渲染了两次。

https://codesandbox.io/s/custom-hook-bfc5j?file=/src/useChat.js

标签: reactjssocket.ioreact-hooks

解决方案


如果您想设置一些副作用一次但还要在多个地方使用结果数据,一种方法是使用上下文功能。

// ws/context.jsx, or similar

const WsContext = React.createContext(defaultValue);

export const WsProvider = props => {
  const [value, setValue] = useState(someInitialValue);
  useEffect(() => {
    // do expensive things, call setValue with new results
  });
  return (
    <WsContext.Provider value={value}>
      {props.children}
    </WsContext.Provider>
  );
};

export const useCustomHook = () => {
  const value = useContext(WsContext);

  // perhaps do some other things specific to this hook usage

  return value;
};

您可以期望钩子在任何作为<WsProvider>React 渲染元素树的后代的组件中工作。

如果您在提供者组件的非后代中使用钩子,则返回的值将是defaultValue我们初始化上下文实例的值。


推荐阅读