当我基于其他状态更新状态时,React给我一个错误:“重新渲染太多。React限制了渲染数量,以防止无限循环。”

时间:2019-07-31 00:19:44

标签: javascript reactjs react-hooks

我正在尝试根据其他状态更新状态,当状态更改时,它会给我一个错误

  

重新渲染过多。 React限制了渲染次数以防止无限循环。

const [filterState, setFilterState] = React.useState([{field: "dateFilter", value: {range: "ANY_TIME", start: "", end: ""}}]);
const [chartData, setChartData] = React.useState({successData, failData, categories, data});

const processData = (res) => {
  const data = res.sort(function(a, b) {
    var keyA = new Date(a.date),
    keyB = new Date(b.date);
    if (keyA < keyB) return -1;
    if (keyA > keyB) return 1;
    return 0;
  });

  categories = data.map((item) => (new Date(item['date'])).toLocaleDateString());
  successData = data.map((item) => item['success']);
  failData = data.map((item) => item['fail']);

  setChartData({...chartData, successData, failData, categories, data});
}

React.useEffect(() => {
  getLineChartCall().then(processData);//async call to get the data
}, []);    

if (filterState.length){
  if (filterState[0].value.range !== 'ANY_TIME') {
    const start = (new Date(filterState[0].value.start)).toISOString();
    const end = (new Date(filterState[0].value.end)).toISOString();

    const filteredData = chartData.data.filter(item => {
      const itemDate = (new Date(item.date).toISOString());
      return (start <= itemDate && end >= itemDate);
    });

    categories = filteredData.map((item) => (new Date(item['date'])).toLocaleDateString());
    successData = filteredData.map((item) => item['success']);
    failData = filteredData.map((item) => item['fail']);

    const data = chartData.data;
    setChartData({...chartData, successData, failData, categories, data});
  }
}

return (
  // render a component based on successData, failData and categories in chartData.
)

更改filterState时执行代码中的以下语句

setChartData({...chartData, successData, failData, categories, data});

这会导致错误

1 个答案:

答案 0 :(得分:0)

此调用setChartData引起了问题,因为它在每个渲染器中都发生。相反,您想要的是仅在其依赖项更改时才重新运行。

if (filterState.length){
  if (filterState[0].value.range !== 'ANY_TIME') {
    const start = (new Date(filterState[0].value.start)).toISOString();
    const end = (new Date(filterState[0].value.end)).toISOString();

    const filteredData = chartData.data.filter(item => {
      const itemDate = (new Date(item.date).toISOString());
      return (start <= itemDate && end >= itemDate);
    });

    categories = filteredData.map((item) => (new Date(item['date'])).toLocaleDateString());
    successData = filteredData.map((item) => item['success']);
    failData = filteredData.map((item) => item['fail']);

    const data = chartData.data;
    setChartData({...chartData, successData, failData, categories, data}); <= HERE****
  }
}

一种替代方法是删除整个部分并添加一个useEffect钩子:

React.useEffect(() => {

  // do the calculations required for setChartData, then:
  setChartData({ ...chartData, successData, failData, categories, data });

}, [/* array of dependencies, when do you want this to be recalculated? */])