简体   繁体   English

将 useEffect 钩子与“异步”一起使用

[英]Using useEffect hook with "async"

How to clean up react request in react hooks.如何清理反应钩子中的反应请求。 I read that in need to enter in my hook AbortController but I don't know how.我读到需要进入我的钩子 AbortController 但我不知道如何。 I using next.js.我使用 next.js。 What are best methods to eliminate this problem?消除此问题的最佳方法是什么? And I get this warning:我得到这个警告:

Warning: can't perform a React state update on an unmounted component.警告:无法对未安装的组件执行 React state 更新。 This is a no-op, but it indicates a memory leak in your application.这是一个无操作,但它表明您的应用程序中存在 memory 泄漏。 To fix, cancel all subscriptions and asynchronous tasks in a useEffect cleanup function.要修复此问题,请在 useEffect 清理 function 中取消所有订阅和异步任务。

This is my custom hook to fetch data:这是我获取数据的自定义钩子:

import { useState, useEffect, useCallback } from 'react'
import { MOVIE_API_URL, MOVIE_KEY } from '../../config'

export const useMovieDetailsFetch = (movieId) => {
  const [state, setState] = useState({})
  const [loading, setLoading] = useState(true)
  const [error, setError] = useState(false)

  const fetchData = useCallback(async () => {
    setError(false)
    setLoading(true)

    try {
      const movieDetailsEndpoint = `${MOVIE_API_URL}movie/${movieId}?api_key=${MOVIE_KEY}`
      const result = await (await fetch(movieDetailsEndpoint)).json()
      const creditsEndpoint = `${MOVIE_API_URL}movie/${movieId}/credits?api_key=${MOVIE_KEY}`
      const creditsResult = await (await fetch(creditsEndpoint)).json()
      // Filtring in crew for directors only
      const movieDirectors = creditsResult.crew.filter(
        (member) => member.job === 'Director'
      )

      setState({
        ...result,
        movieDirectors,
        actors: creditsResult.cast,
      })
    } catch (error) {
      setError(true)
    }
    setLoading(false)
  }, [movieId])

  useEffect(() => {
   
    fetchData()
  }, [fetchData])

  return [state, loading, error]
}

Using an abort controller , in its rawest form:使用最原始的形式中止 controller

const controller = new AbortController();
const { signal } = controller;
...

fetch(url, { signal });

...
// abort
controller.abort();

To abort an in-flight fetch in effect hook中止正在进行的fetch in effect hook

useEffect(() => {
  const controller = new AbortController();
  const { signal } = controller;
  fetch(url, { signal });

  return () => {
    controller.abort(); // abort on unmount for cleanup
  };
}, []);

I found this article very informative when I needed to develop a way to cancel fetch requests.当我需要开发一种取消获取请求的方法时,我发现这篇文章非常有用。

Edit编辑

The signal needs to be added to the fetch requests options object.signal需要添加到fetch请求选项 object。 You can also define the async fetchData function inside the effect (this is normal), so it's all enclosed in the effect hook's callback scope.也可以在 effect 内部定义async fetchData function(这是正常的),所以都包含在 effect hook 的回调 scope 中。

export const useMovieDetailsFetch = (movieId) => {
  const [state, setState] = useState({})
  const [loading, setLoading] = useState(true)
  const [error, setError] = useState(false)

  useEffect(() => {
    const controller = new AbortController();
    const { signal } = controller;

    const fetchData = async () => {
      setError(false);
      setLoading(true);

      try {
        const movieDetailsEndpoint = `${MOVIE_API_URL}movie/${movieId}?api_key=${MOVIE_KEY}`;
        const result = await (
            await fetch(movieDetailsEndpoint, { signal })
          ).json();
        const creditsEndpoint = `${MOVIE_API_URL}movie/${movieId}/credits?api_key=${MOVIE_KEY}`;
        const creditsResult = await (
            await fetch(creditsEndpoint, { signal })
          ).json();
        // Filtring in crew for directors only
        const movieDirectors = creditsResult.crew.filter(
          (member) => member.job === 'Director'
        );

        setState({
          ...result,
          movieDirectors,
          actors: creditsResult.cast,
        });
      } catch (error) {
        setError(true);
      }
      setLoading(false);
    }

    fetchData();

    return () => controller.abort();
  }, [movieId]);

  return [state, loading, error];
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM