Отрисовал больше перехватов, чем во время предыдущего рендеринга с использованием useEffect

#reactjs #react-hooks

#reactjs #реагирующие перехваты

Вопрос:

У меня есть компонент с массивом объектов, который, помимо прочего, я фильтрую на основе строки. Проблема в том, что когда я пытаюсь установить возврат этого фильтра в локальное состояние, он выдает ошибки, причину которых я не совсем понимаю.

 import React, { useState, useEffect } from 'react';
import { useQuery } from '@apollo/react-hooks';
import gql from 'graphql-tag'
const ProductsGrid = () => {


const [productsList, setProductsList] = useState([]);
  const { loading, data } = useQuery(GET_PRODUCTS);
  if (loading) return <div><h4>bla bla bla</h4></div>
  const { merchants } = data;
  let filtered = [];
  merchants.map(merchant => {
    merchant.products.map(product => {
      if (product.name.includes('Polo')) {
        filtered.push(product);
      }
    })
  })
  console.log({ filtered });
}
  

Это выводит следующее: введите описание изображения здесь

Итак, поскольку я хочу, чтобы этот массив был в моем состоянии, я решил сделать это: setProductsList(filtered); и что произошло после вставки этой строки, так это:

введите описание изображения здесь

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

Итак, я подумал об использовании useEffect для достижения ожидаемого поведения здесь.

 useEffect(() => {
console.log('useeffect', data);
if (data) {
  const { merchants } = data;
  console.log({merchants })
  let filtered = [];
  merchants.map(merchant => {
    merchant.products.map(product => {
      if (product.name.includes('Polo')) {
        filtered.push(product);
        // console.log({ filtered });
      }
    })
  })
  console.log({ filtered });
  setProductsList(filtered);
}
  

}, [данные])

и результат был таким: введите описание изображения здесь

Итак, я понимаю, что здесь происходит и в чем заключается эта последняя ошибка. Я предполагаю, что мой подход направлен в правильном направлении, используя useEffect для запуска функции только один раз.

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

1. показать полный код компонента.

2. @adel это полный код. Помимо того, что вы видите здесь, есть только return <div> abc</div>, который не имеет значения.

3. Ваш вопрос может содержать полный код, но он фрагментарный — мы не знаем, как useEffect он вписывается во все остальное. Было бы полезно, если бы вы могли показать полный компонент или, по крайней мере, его достаточное количество, чтобы мы могли видеть все случаи использования хуков на месте.

4. @backtick jsfiddle.net/4v2u10yr/1 весь сценарий компонента здесь.

Ответ №1:

Ваша проблема связана с useEffect вызовом, возникающим после if (loading) условия, которое возвращается раньше.

Вызов перехватов после оператора условного возврата является незаконным, поскольку нарушает гарантию того, что перехваты всегда вызываются в точно таком же порядке при каждом рендеринге.

 const { loading, data } = useQuery(GET_PRODUCTS);
const [productsList, setProductsList] = useState([]);
if (loading)
  return (
    <div>
      <h4>bla bla bla</h4>
    </div>
  );  // <-- Cannot use hooks after this point
useEffect(/* ... */)
  

Чтобы исправить, переместите useEffect вызов перед условным.