React使用状态的异步函数钩住穷举-无限循环

时间:2019-11-15 12:26:58

标签: reactjs react-hooks eslint

我正在尝试处理一个异步功能,以便在数据库中插入数据。不幸的是,押金react-hooks/exhaustive-deps要求我在score中添加useCallback状态。虽然当我添加此应用程序时,我的应用程序处于无限循环状态。

当我在回调要求行上添加eslint-disable-line时,我的代码运行得很好。为什么会有此规则?如何在不禁用eslint规则的情况下正确解决它?

import React, { useState, useEffect, useCallback } from 'react';
import { useSelector, useDispatch } from 'react-redux';

import { insertData } from 'ducks/data';

const App = () => {
  const dispatch = useDispatch();
  const sliderData = useSelector((state) => state.data.sliders);
  const [score, setScore] = useState(0);

  const handleData = useCallback(() => {
    dispatch(insertData(score));
  }, [dispatch]); // eslint-disable-line

  useEffect(() => {
    for (const [key, value] of Object.entries(sliderData)) {
      const sliders = Object.values(value);
      const totalSliderScore = sliders.reduce((a, b) => a + b, 0);

      setScore((prevScore) => prevScore += totalSliderScore);

      // Last slider in array
      if (key === 'lastKey') {
        handleData();
      }
    }
  }, [sliderData, handleData]);

  return ...
};

export default App;

2 个答案:

答案 0 :(得分:1)

您可以创建最新分数的参考,以免引起循环

    const [score, setScore] = useState(0);
    const latestScore = useRef();

    const handleData = useCallback(() => {
    dispatch(insertData(latestScore));
    }, [dispatch,latestScore]); // eslint-disable-line

    useEffect(() => {
        ...
        latestScore.current = score
        }
    }, []);

答案 1 :(得分:0)

useCallback中使用的任何状态变量都应包括在依赖项列表中,否则您可能会获得该变量的陈旧数据。

const handleData = useCallback(() => {
dispatch(insertData(score));
}, [dispatch, score]);

以及为什么在handleData的依赖项列表中需要函数useEffect?这不是造成循环的原因。我认为也可以更改以下内容来解决无限循环。

useEffect(() => {
for (const [key, value] of Object.entries(sliderData)) {
  const sliders = Object.values(value);
  const totalSliderScore = sliders.reduce((a, b) => a + b, 0);

  setScore((prevScore) => prevScore += totalSliderScore);

  // Last slider in array
  if (key === 'lastKey') {
    handleData();
  }
}
}, [sliderData]);