useEffect поддерживает функцию обратного вызова, вызывая бесконечный цикл - PullRequest
2 голосов
/ 19 июня 2019

У меня есть проблема, очень похожая на эту - Как исправить отсутствующую зависимость в React Hook useEffect .

Есть одно ключевое отличие - я передаю функцию выборки ребенкукомпонент, вызываемый из useEffect , поэтому я не могу просто переместить функцию в тело эффекта.Функция fetch воссоздается при каждом рендеринге и вызывает бесконечный цикл.У меня есть другое состояние локального компонента, которое я хочу вызвать эффект.

У меня в основном есть Контейнерный компонент и Презентационный компонент.MyPage является родителем MyGrid и устанавливает все состояние редукса:

const MyPage = () => {

  const dispatch = useDispatch();
  const items= useSelector(selectors.getItems);
  const fetching = useSelector(selectors.getFetching);
  const fetchItems = opts => dispatch(actions.fetchItems(opts));

  return (
    <>
      {fetching && <div>Loading...</div>}
      <h1>Items</h1>
      <MyGrid
        items={items}
        fetchItems={fetchItems}
        fetching={fetching}
      />
    </>
  );

}

const MyGrid = ({ fetchItems, items, fetching }) => {

  const [skip, setSkip] = useState(0);
  const take = 100;
  const [sorts, setSorts] = useState([]);

  // when query opts change, get data
  useEffect(() => {

    const options = { skip, take };
    const sortString = getSortString(sorts);
    if (sortString) options['sort'] = sortString;
    fetchItems(options);

  }, [fetchItems, skip, sorts]);

В «MyGrid» «skip» и «sorts» могут изменяться и должны вызывать эффект «огонь».

"fetchItems" воссоздается каждый раз и вызывает бесконечный цикл.Это моя проблема.

Теперь правило eslint response-hooks / исчерпывающее-deps заставляет меня помещать fetchItems в список зависимостей.У меня есть более приятные настройки для автоматического исправления при сохранении, что делает его еще хуже.

Я знаю, что шаблон «Контейнер / презентация» не соответствует стилю с перехватчиками, но он хорошо работает для моей ситуации - я могу разрешить динамически заменять MyGrid для MyListи я не хочу повторять все вещи с избыточностью в каждом дочернем компоненте.

Я пытался useCallback и useMemo , но eslint просто заставляет меня помещать все то же самоезависимости в параметре массива зависимостей.

Есть ли другой способ, кроме отключения правила eslint

// eslint-disable-next-line react-hooks/exhaustive-deps

, чтобы эта работа работала?

1 Ответ

1 голос
/ 19 июня 2019

Есть два способа, вы можете заставить его работать.

Во-первых , используя useCallback для fetchItem, например

const fetchItems = useCallback(opts => dispatch(actions.fetchItems(opts)), [dispatch, actions]);

Во-вторых , используя dispatch непосредственно в дочернем компоненте

const dispatch = useDispatch();
 useEffect(() => {

    const options = { skip, take };
    const sortString = getSortString(sorts);
    if (sortString) options['sort'] = sortString;
    dispatch(actions.fetchItems(options));

  }, [dispatch, actions, skip, sorts]);
...