如何在功能正常的React组件中正确设置setState?

时间:2020-05-08 11:32:43

标签: reactjs asynchronous fetch react-hooks state

我已经在类似这样的功能性React组件中实现了React State Hook:

const [tableData, setTableData] = useState([]);

在我的组件中,我执行一个异步API请求,并在表中填充结果:

const loadArtikel = () =>
    fetch("https://my-api.com/api/v1/xyz")
        .then(res => (res.ok ? res : Promise.reject(res)))
        .then(res => res.json())


return (
    <Async promiseFn={loadArtikel}>
        {({ data, err, isLoading }) => {
            if (isLoading) return (<div>Loading...</div>)
            if (err) return `Something went wrong: ${err.message}`

            if (data) {
                var tempData = [];
                Object.keys(data.artikel).map(function (keyName, keyIndex) {
                    tempData.push(data.artikel[keyName]);
                });
                setTableData(tempData); // this line is causing problems
                return (
                    <MaterialTable
                        data={tableData}
                    />
                )
            }
        }}
    </Async>
);

当我使用setTableData()时,这会导致反复重复获取请求。 我不知道为什么。

1 个答案:

答案 0 :(得分:1)

这实际上会导致无限循环,因为组件在每次更改其属性/状态时都会重新渲染。在这种情况下,您将在组件返回内直接调用setTableData,这将更新状态。反过来,这将导致该组件再次重​​新呈现,从而导致一遍又一遍地调用请求。

如果只应调用此方法一次,则应在useEffect挂钩中使用它,并使用一个空数组作为依赖项数组:

useEffect(() => {  
  fetch('https://my-api.com/api/v1/xyz')
    .then(response => response.json())
    .then(result => {
      // process data
      const tempData = ......;
      setTableData(tempData);
    });     
}, []);


return (
  <>
  {
    tableData.length 
      ? (
        <MaterialTable
          data={tableData}
        />
      : <div>Loading...</div>
  } 
  </>
);