使用提取API提取数据和setState时,多次反应useEffect循环

时间:2020-06-15 03:14:37

标签: javascript reactjs fetch-api use-effect use-state

为什么这多次触发fetchDataconsole.log似乎几乎无限循环吗?如何使它仅在加载时运行一次并在以后调用fetchData()时仅触发一次?我在这里做错了什么或想念什么?

const [data, setData] = useState(null);

  let fetchData = React.useCallback(async () => {
    const result = await fetch(`api/data/get`);
    const body = await result.json();
    setData(body);
    console.log(data)
  },[data])

  useEffect(() => {
    fetchData();
  },[fetchData]);

更新(其他问题):如何在data之前等待return()填充,下面的内容由于最初为空而出现错误?data.map is not a function

return (
    <select>
        {data.map((value, index) => {
            return <option key={index}>{value}</option>
        })}
    </select>
)

1 个答案:

答案 0 :(得分:4)

useCallback钩子中,您将data作为依赖项进行传递,并且还通过调用setData同时在回调内部更改数据值,这意味着每次数据值更改{ {1}}将被重新初始化。

fetchData钩子useEffect中是一个依赖项,这意味着每次fetchData的更改fetchData都会被触发。这就是为什么出现无限循环的原因。

因为要在安装组件时一次获取数据,所以我认为这里useEffect是不必要的。无需不必要地记住函数useCallback

解决方案

fetchData

如果要记录const [data, setData] = useState(null); useEffect(() => { const fetchData = async () => { try { const result = await fetch(`api/data/get`); const body = await result.json(); setData(body); } catch(err) { // error handling code } } // call the async fetchData function fetchData() }, []) 的值更改时的值,则可以使用另一个data来记录。例如,

useEffect

P.S。 -同样不要让诺言无法兑现,请使用useEffect(() => { console.log(data) }, [data]) 块来处理错误。我已经更新了解决方案,使其包括try..catch块。

编辑- 其他问题的解决方案 有两种可能的解决方案,

由于您期望try...catch的值是API调用后的数组,因此您可以将data的值初始化为一个空数组,例如,

data

但是,如果由于某种原因,您必须将const [data, setData] = useState([]); 的值初始化为data。这是呈现您从API调用返回的信息的方法。

null

请勿将// using short-circuit evaluation return ( <select> {data && data.length && data.map((value) => { return <option key={`select-option-${value}`}>{value}</option> })} </select> ) // using a ternary return ( <div> { data && data.length ? (<select> { data.map(value => <option key={`select-option-${value}`}>{value}</option>) } </select> ) : <div>Data is still loading...</div> } </div> ) 用作indexes,请使用唯一的密钥。