为什么在循环内设置useState会有不同的表现?

时间:2020-06-30 00:17:26

标签: reactjs react-hooks react-state use-state

有人可以向我解释以下代码段吗?为什么handleClick()无法正常工作(仅设置了newData的数据属性中的1或2)而handleClick2()却正常工作。

我猜测问题是由于循环造成的(因为这是唯一的区别),但是为什么循环会导致这种效果呢?

沙盒链接:https://codesandbox.io/s/restless-surf-u9i5s?file=/src/App.js:0-969

import React, { useState, useEffect } from "react";
import "./styles.css";


const App = () => {
  const [newData, setNewData] = useState({
    data1: '',
    data2: '',
    data3: '',
    data4: ''
  })

  const handleClick = () => {
    let fields = ['data1', 'data2', 'data3', 'data4']
    let field
    for (field of fields) {
        setNewData(oldState => ({...oldState, [field]: 'test'}))
    }
  }

  const handleClick2 = () => {
    setNewData(oldState => ({...oldState, data1: 'test'}))
    setNewData(oldState => ({...oldState, data2: 'test'}))
    setNewData(oldState => ({...oldState, data3: 'test'}))
    setNewData(oldState => ({...oldState, data4: 'test'}))
  }

  useEffect(() => {
    console.log('State: ' + JSON.stringify(newData))
  }, [newData])

  return (
    <div className="App">
      <button onClick={handleClick}>Click</button>
      <button onClick={handleClick2}>Click2</button>
    </div>
  );
}

export default App

1 个答案:

答案 0 :(得分:1)

原因是:

setNewData是异步功能。当您以某种方式调用setNewData时,React将在事件循环中推送其回调函数,然后在主线程为空时在主线程中将其回调。在主setNewData中调用field回调函数时,是test4,因为for (field of fields)同步函数。 ==>只有setNewData(oldState => ({...oldState, data4: 'test'}))被呼叫4次。

您可以在field回调函数中记录setNewData并查看其值。

for (field of fields) {
  console.log(field)
  setNewData(oldState => {
    console.log(field)
    return { ...oldState, [field]: "test" }
  })
}

Codesandbox for it