繁体   English   中英

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

[英]Using useEffect hook with "async"

如何清理反应钩子中的反应请求。 我读到需要进入我的钩子 AbortController 但我不知道如何。 我使用 next.js。 消除此问题的最佳方法是什么? 我得到这个警告:

警告:无法对未安装的组件执行 React state 更新。 这是一个无操作,但它表明您的应用程序中存在 memory 泄漏。 要修复此问题,请在 useEffect 清理 function 中取消所有订阅和异步任务。

这是我获取数据的自定义钩子:

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]
}

使用最原始的形式中止 controller

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

fetch(url, { signal });

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

中止正在进行的fetch in effect hook

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

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

当我需要开发一种取消获取请求的方法时,我发现这篇文章非常有用。

编辑

signal需要添加到fetch请求选项 object。 也可以在 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