Как остановить перехватчик React useEffect от рендеринга дублированных данных

У меня есть компонент, в котором я использую useEffect, а внутри вызываю функцию fetchLatest(). fetchLatest() - это действие, которое отправляет сетевой запрос на получение всех фильмов, выпущенных в текущем году. Я использую Redux, и в моем магазине у меня есть state.movies.latest, и каждый раз, когда я запускаю приложение в первый раз, последняя строка фильмов является точной, без дублирования данных. Когда я визуализирую другой компонент и возвращаюсь к своему домашнему компоненту, где я делаю fetchLatest, я получаю дублированные данные.

Я понял, что моя проблема в том, что в моих редукторах я возвращаю что-то вроде ...

return {
    ...state,
    latest: [...state, ...payload]
}

где payload - массив объектов (фильмов).

Поэтому я поменял редукторы на ...

return {
    ...state,
    latest: [...payload]
}

Теперь это работает, и я не получаю дублирующихся данных, но меня беспокоит, что я не понимаю или делаю это правильно. Если бы я должен был использовать useEffect и иметь свою функцию fetchLatest в моем хуке useEffect и передать ее в зависимости от моего понимания, моя функция fetchLatest будет воссоздаваться после каждого цикла рендеринга как совершенно новый объект. Поскольку у меня уже есть в магазине мой latest массив фильмов, я не хочу каждый раз повторно отображать новый объект, вызывая добавление в мой магазин state.movies.latest дублированных данных. По крайней мере, я верю, что это то, что он делает.

Я решил, что, возможно, мне следует использовать useCallback, чтобы гарантировать, что этот новый объект fetchLatest не будет создан, если его зависимости не изменятся.

Так что я не уверен в том, что, может быть, я смогу получить обновленный редуктор в том виде, в котором он есть сейчас, а также useCallback, чтобы гарантировать отсутствие бесконечных циклов для воссоздания моей функции fetchLatest каждый раз в качестве нового объекта, когда я перестраиваю этот компонент?

Кроме того, я, возможно, не понимаю, что делает useCallback, потому что я пробовал перед использованием useCallback и моим редуктором в том виде, в котором он был у меня изначально, и, насколько я понимаю, если ничего не изменилось, то почему мой fetchLatest запускается, когда я перестраиваю компонент. Мне нужны только мои последние фильмы, которые у меня уже есть в магазине, когда я впервые устанавливаю свой компонент

мой код для этого компонента выглядит так

const Latest = ({ fetchLatest, latest }) => {
  useEffect(() => {
    fetchLatest();
  }, [fetchLatest]);

  return (
    <div className='genre-temp'>
      <h3 className='text-light'>Latest</h3>
      <div className='movies-container d-flex'>
        {latest.map((movie) => (
          <Movie
            key={movie.id}
            movieId={movie.id}
            image={movie.image}
            title={movie.title}
            description={movie.description}
          />
        ))}
      </div>
    </div>
  );
};

и изначально я пытался добавить этот useCallback и вызвать handleFetching в свой useEffect и передать его как зависимость.

const handleFetching = useCallback(() => {
    fetchLatest()
}, []);

Тем не менее, useCallback в сочетании с useEffect, хотя мой редуктор все еще есть ...

return {
    ...state,
    latest: [...state, ...payload]
}

по-прежнему будет запускаться каждый раз, когда компонент перестраивается.


person Michael Torres    schedule 19.11.2020    source источник


Ответы (1)


Попробуйте добавить состояние запроса к вашему объекту состояния. Затем вы сможете проверить, выбран ли список. Обычно я использую четыре состояния для запросов: инициализация, запрос, успех, сбой. Вот примерный пример запроса:

if (requestState !== 'request' && requestState !== 'success') {
    try {
        setRequestState('request');
        const response = await fetchList();
        setList(response);
        setRequestState('success');
    catch (e) {
        setRequestState('failure');
        log(e);
    }
}

Если у вас есть состояние запроса, вы всегда будете знать, когда вам нужно запросить данные, показать счетчик, показать сообщение об ошибке и т. Д. Надеюсь, вы уловили идею.

P.S. В вашем коде это должно быть:

{
    ...state,
    latest: [...payload]
}

latest: [... state.latest, ... payload] не будет работать так, как вы ожидаете. последнее: [... состояние, ... полезная нагрузка] выглядит неправильно.

person Alex Shushunov    schedule 20.11.2020