如何清除在use外部创建的异步任务

时间:2019-08-02 13:45:33

标签: reactjs react-hooks

我创建了一个自定义钩子useFetch,该钩子返回可以在其他组件中使用的fetch函数。它使用一个承诺来获取内部的一些数据。我的目标是清理使用该自定义钩子的未完成诺言,如果该组件已卸载。

我该怎么做?我使用useRef进行了尝试,但是还没有成功。仍然收到Can't perform a React state update on an unmounted component.警告。

const useFetch = (url) => {
  const [isFetching, setIsFetching] = useState(false)
  const handler = useRef(null)

  useEffect(() => () => {
    if (handler.current !== null) {
      handler.current.cancel()
    }
  }, [])

  return (options) => {
    handler.current = window.fetch(url, options)
    setIsFetching(true)

    return handler.current.then(() => {
      handler.current = null
      setIsFetching(false)
    })
  }
}

export default () => {
  const fetchData = useFetch('www.tld')

  useEffect(() => {
    fetchData({}).then(() => console.log('done'))
  }, [])

  return null
}

请注意,此示例中的诺言可以通过.cancel()取消(因此,这不是问题)。

1 个答案:

答案 0 :(得分:0)

从挂钩中返回cancel()作为绑定回​​调。然后由消费者来阻止它:

const useFetch(url) {
  const [isFetching, setIsFetching] = useState(false)
  const handler = useRef(null)

  function run(options) {
    handler.current = window.fetch(url, options)
    setIsFetching(true)
    ...
  }
  function cancel() {
    if(handler.current) {
      handler.current.cancel()
    }
  }

  return {run, cancel}
}

...
function OtherComponent({userId}) {
  const [userData, setUserData] = useState(null);

  const {run, cancel} = useFetch(`/user/${userId}`);

  useEffect(() => {
    run(options).then(setUserData);

    return cancel; // it's up to consumer code to stop request
  }, [userId]); 
}