Использование крючка useEffect с "asyn c" - PullRequest
0 голосов
/ 06 апреля 2020

Как убрать ответный запрос в реагирующих крючках. Я читал, что нужно перебрать AbortController, но я не знаю как. Я пользуюсь следующим. js. Каковы лучшие методы, чтобы решить эту проблему? И я получаю это предупреждение:

Предупреждение. Невозможно выполнить обновление состояния React для неустановленного компонента. Это неоперация, но она указывает на утечку памяти в вашем приложении. Чтобы исправить, отмените все подписки и асинхронные задачи в функции очистки useEffect.

Это мой пользовательский хук для извлечения данных:

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

1 Ответ

0 голосов
/ 06 апреля 2020

Использование контроллера прерывания в его исходном виде:

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

fetch(url, { signal });

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

Чтобы прервать эффект fetch в полете

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

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

I нашел статью очень информативной, когда мне нужно было разработать способ отмены запросов на выборку.

Редактировать

Необходимо добавить signal к fetch объекту параметров запросов. Вы также можете определить функцию async fetchData внутри эффекта (это нормально), так что все это включено в область обратного вызова ловушки эффекта.

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