在循环中调用setState只会更新状态1次

时间:2016-02-07 01:38:23

标签: javascript reactjs

是否有理由在循环中调用setSate()会阻止它多次更新状态?

a very basic jsbin突出了我所看到的问题。有两个按钮。一个将状态计数器更新为1.另一个在循环中调用One的基础函数 - 这似乎会多次更新状态。

我知道这个问题的几个解决方案,但我想确保我首先理解这里的基础机制。为什么不能在循环中调用setState?我是否笨拙地编码阻止了预期的效果?

8 个答案:

答案 0 :(得分:10)

来自React Docs

  

setState()不会立即改变this.state但会创建一个   待定状态转换。调用后访问this.state   方法可以返回现有值。没有   保证调用setState和调用的同步操作   为获得业绩增长而受到批评。

基本上,不要在循环中调用setState。这里发生的正是文档所指的内容:this.state正在返回之前的值,因为尚未应用挂起状态更新。

答案 1 :(得分:1)

我遇到了同样的问题。但尝试采用一种不同的方法。

iterateData(data){
  //data to render
   let copy=[];
   for(let i=0;<data.length;i++){
     copy.push(<SomeComp data=[i] />) 
    }
    this.setState({
      setComp:copy
    });
 }
 render(){
   return(
     <div>
       {this.state.setComp}
    </div>
   );
 }

我希望这会有所帮助。

答案 2 :(得分:1)

在循环中更新状态有一种很好的方法。只需创建一个空变量,将其值设置为更新状态,调用setState(),并将此变量传递给它:

const updatedState = {};

if (vars.length) {
  vars.forEach(v => {
    updatedState[v] = '';
    this.setState({
      ...this.state
      ...updatedState,
    });
  });
}

答案 3 :(得分:1)

你必须使用类似的东西:

const MyComponent = () => {
  const [myState, setMyState] = useState([]);

  const handleSomething = (values) => {
    values.map((value) => {
      setMyState((oldValue) => [...oldValue, { key: value.dataWhatYouWant }]);
    }
  }

  return (<> Content... </>);
}

答案 4 :(得分:1)

实际上 setState() 方法是异步的。相反,您可以像这样实现它

manyClicks() {
var i = 0;
for (i = 0; i < 100; i++) {
  //this.setState({clicks: this.state.clicks + 1}); instead of this
  this.setState((prevState,props)=>({
      clicks: ++prevState.clicks
   }))
   }
 }

答案 5 :(得分:0)

基本上,setState是异步调用的。它还具有回调函数,一旦状态发生变异,您就可以利用它来执行某些操作。 此外,如果一个接一个地调用多个setStates,它们将按照之前的编写方式进行批处理。

答案 6 :(得分:0)

我在创建导入项目的功能时遇到了这个问题。 由于导入项目的数量可能很大,我需要向站点用户提供反馈(如进度条),以便他们知道他们不会坐在那里等待任何事情。

我们知道我们不能在循环中 setState,我采用了不同的方法,通过递归运行任务。

这是一个示例代码 https://codesandbox.io/s/react-playground-forked-5rssb

答案 7 :(得分:-5)

我能够使你的代码工作,通过执行以下操作在循环中调用setState:

 manyClicks() {
   for (i = 0; i < 100; i++) {
     this.setState({clicks: this.state.clicks += 1})
   }
 }
enter code here

希望这有帮助!