如何在反应中正确破坏上下文?

Fla*_*ken 3 reactjs react-hooks

我正在创建一个 React上下文

这个上下文会提供一个服务,这个服务会订阅一些外部事件来保持更新。为了防止任何泄漏,我必须在上下文被破坏时通过取消订阅来清理此服务。

与我们可以在组件被销毁时返回回调不同useEffect,我不知道如何对上下文执行相同的操作。如何做到这一点,或者什么是正确的选择?

注意:我的直觉是我应该在 useEffect() 中创建一项服务并将其设置为上下文,但对于看起来简单的依赖注入来说似乎很麻烦。

Ori*_*ori 5

创建一个上下文提供程序组件,将您的服务封装在一个useEffect块中。订阅服务通行证后,存储引用您希望上下文的使用者使用的服务/功能/等的状态。

useEffect有一个清理函数,您可以在组件卸载时使用该函数取消订阅:

const ServiceContext = createContext();

const ServiceProvider = ({ initService, children }) => {
  const [service, setService] = useState(() => initService()); // you can initialize the service here

  useEffect(() => {
    // or initialize the service here if the process is async
    setService(serviceInstance);
    
    return () => {
      // cleanup unsubscribe from service
    };
  }, []);
       
  return (
    <ServiceContext.Provider value={service}>
      {children}
    </ServiceContext.Provider>
  );
}
Run Code Online (Sandbox Code Playgroud)

与问题没有直接关系 - 我通常添加一个简单的自定义钩子包装器useContext

const useService = () => useContext(ServiceContext);
Run Code Online (Sandbox Code Playgroud)

然后在你的组件中:

const service = useService();
Run Code Online (Sandbox Code Playgroud)

另一种选择是创建一个惰性服务提供者 - 该服务仅在useService调用时才初始化:

const ServiceContext = createContext();

const ServiceProvider = ({ children }) => {
  const service = useRef(null); // store a reference to the service

  useEffect(() => () => {
      // cleanup unsubscribe from service
      // service.current?.unsubscribe() for example
  }, []);
  
  const getService = useCallback(() => {
    if(!service.current) service.current = initService // initialize if doesn't exist on ref
    
    return service.current
  }, []);
       
  return (
    <ServiceContext.Provider value={getService}>
      {children}
    </ServiceContext.Provider>
  );
}

const useService = () => {
  const getService = useContext(ServiceContext)
  
  return getService()
}
Run Code Online (Sandbox Code Playgroud)