Как мне справиться с двумя крючками useEffect, когда одна зависимость useEffect влияет на другую зависимость useEffect?

#reactjs #react-hooks #use-effect #react-state-management

Вопрос:

Поэтому я работаю над веб-сайтом, который имеет бесконечную прокрутку и сортировку/фильтрацию. Проблема в том, что при изменении sortBy метода мне нужно сбросить смещение для разбиения на страницы с бесконечной прокруткой.

Вот код для компонента:

 function Listings({ setListingCount, sortBy }) {
  const [listings, setListings] = useState([]);
  const [isInitialLoading, setIsInitialLoading] = useState(true);
  const [isLoading, setIsLoading] = useState(true);
  const [apiError, setApiError] = useState(false);
  const [offset, setOffset] = useState(0);
  const [hasMore, setHasMore] = useState(true);
  const limit = 12;

  const observer = useRef();
  const lastListingElementRef = useCallback((node) => {
    if (isLoading) {
      return;
    }

    if (observer.current) {
      observer.current.disconnect();
    }

    observer.current = new IntersectionObserver((entries) => 
  {
      if (entries[0].isIntersecting amp;amp; hasMore) {
        setOffset((prevOffset) => prevOffset   limit);
      }
    });
    if (node) {
      observer.current.observe(node);
    }
  }, [isLoading, hasMore]);

  function resetListings() {
    setListings([]);
    setIsInitialLoading(true);
    setApiError(false);
    setOffset(0);
    setHasMore(true);
    setListingCount('0');
  }

  useEffect(() => {
    resetListings();
  }, [sortBy]);

  useEffect(async () => {
    try {
      setIsLoading(true);
      const response = await axios.get(
        'listings',
        {
          params: {
            offset,
            limit,
            sb: sortBy
          }
        }
      );
      setListings((prevListingIds) => [
        ...new Set(
          [...prevListingIds, ...response.data.rows]
        )
      ]);
      setListingCount(response.data.count);
      setHasMore(response.data.rows.length > 0);
      setIsLoading(false);
      setIsInitialLoading(false);
    } catch (error) {
      setApiError(true);
      setIsLoading(false);
      setIsInitialLoading(false);
    }
  }, [sortBy, offset]);

  return();
}
 

Первый useEffect используется для сброса состояний в случае sortBy изменений. Второй useEffect используется для загрузки большего количества данных всякий раз, когда изменяется смещение или если sortBy изменения. В настоящее время происходит то, что пользователь изменяет sortBy значение, когда смещение не равно 0 (скажем, 12), затем второй useEffect делает запрос get offset = 12 , прежде чем первый useEffect сможет сбросить смещение обратно до 0. Но как только смещение сбрасывается на 0 первым useEffect , выполняется другой запрос get offset = 0 , так что теперь он отображает 24 списка вместо 12, и это в неправильном порядке.

Как я должен иметь дело с useEffect s, которые не гарантированно будут выполняться в том порядке, в котором я этого ожидаю? Есть ли другой способ реализовать эту логику? Спасибо вам за любую помощь, которая может быть оказана!

Комментарии:

1. Я немного сбит с толку, но пытаюсь понять. Порядок вызовов useEffect() зависит от порядка их срабатывания. Я бы присмотрелся к этому повнимательнее. Кроме того, асинхронность может вас испортить. Глядя на управление состоянием, которое у вас здесь есть, я бы предложил вам установить логическое значение состояния или что-нибудь дополнительное. Тогда вы можете использовать это в своем эффекте использования. Допустим, вы назвали это [needsUpdate, setNeedsUpdate]. В конце эффекта использования вы можете изменить состояние обновления потребностей и запустить другой эффект использования.

2. Таким образом, изменение значений не вызывает эффекта использования, а вызывает изменение нового значения. Кроме того, setState запустит повторный запрос для вас на затронутых компонентах.

3. @sloont Привет, спасибо за ваш ответ! Поэтому я пытаюсь сделать это прямо сейчас, но у меня возникла проблема, потому что мне нужен второй эффект использования, который будет выполняться либо при изменении смещения, либо при изменении сортировки. Но смещение также должно быть сброшено до 0 при изменении сортировки. Поэтому, если я установлю needsUpdate значение true в конце первого эффекта использования, второй эффект использования все равно будет срабатывать дважды: один раз, когда offset установлено значение 0, и один раз, когда needsUpdate установлено значение true. Это связано с тем, что я меняю переменные зависимости для второго эффекта использования на [needsUpdate, offset] . Надеюсь, в этом есть смысл

4. Я не совсем уверен, что это лучший способ сделать это. Потенциально вы могли бы превратить разделы функций в обещания, а затем пообещать. все это значит, что вы ждете окончания каждого процесса, прежде чем продвигаться вперед.