React useEffect清理功能取决于异步等待结果

时间:2019-07-19 15:30:21

标签: javascript reactjs async-await react-hooks

我有一个react组件,该组件异步获取一些资源,然后订阅资源更改。

问题在于清理功能不在此资源的关闭范围内:

useEffect(() => {
  const onResourceChange = () => { 
    console.log('resource changed');
  };

  getSomeResource().then(resource => {
    resource.subscribe(onResourceChange);
  });

  return () => {
    resource.unsubscribe(onResourceChange); // Error! resource is undefined
  }
}, []);

由于不允许在useEffect中使用异步函数,因此在useEffect的清除函数中取消订阅该资源的最佳方法是什么?

2 个答案:

答案 0 :(得分:4)

我看到这里有两个“副作用”。

  1. 获取资源(需要发生一次,依赖性hiddenimports=['pyodbc'],
  2. 订阅/取消订阅回调(需要在资源更改,依赖项,[]上发生)

所以我

  1. 将它们分为两个“效果”(步骤,每个步骤处理一个副作用)
  2. 并将其提取到自定义钩子中
[resource]

如您所见,第一个 function useResource() { const [resource, setResource] = useState(undefined) const onResourceChange = () => console.log('resource changed'); // Get the resource, initially. useEffect(() => { getSomeResource(setResource) }, []) // When the resource is retrieved (or changed), // the resource will subscribe and unsubscribe useEffect(() => { resource.subscribe(onResourceChange) return () => resource.unsubscribe(onResourceChange) }, [resource]) } // Use it like this function App() { useResource() return <>your elements</> } 仅负责获取“资源”,而第二个useEffect负责取消/订阅回调。

并检查每个useEffect中的deps列表(前者为空useEffect,而后者取决于[]

答案 1 :(得分:1)

这是一个解决方案,可能很丑...但是仍然是解决方案:)

useEffect(() => {
    const onResourceChange = () => { 
        console.log('resource changed');
    };

    let data = {};

    getSomeResource().then(resource => {
        data.resource = resource;
        resource.subscribe(onResourceChange);
    });

    return () => {
        data.resource && data.resource.unsubscribe(onResourceChange); // Error! resource is undefined
    };
}, []);