首页 > 解决方案 > 为什么在循环内设置 useState 执行不同?

问题描述

有人可以向我解释以下代码片段吗?为什么 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

标签: reactjsreact-hooksreact-stateuse-state

解决方案


原因是:

setNewData是异步函数。当你setNewData以某种方式调用时,React 会在事件循环中推送它的回调函数,然后在主线程为空时在主线程中调用它。在setNewDatamain 中调用回调函数fieldtest4因为 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" }
  })
}

它的代码沙盒


推荐阅读