setState没有更新状态:ReactJS

时间:2017-04-10 13:02:02

标签: reactjs

我觉得我已经在阳光下尝试了所有东西但是必须遗漏一些非常明显的东西。在下面的addItem() function中,我试图将一个新项目推送到一个数组并更新状态,但无论我做什么,状态只是从最初的数组中改变。

当我在console.log newListItems中包含新项目时,所以到目前为止所做的一切都是有效的,它是不会更新的实际状态。我错过了什么?

addItem方法:

addItem(text){
    var newListItems = this.state.listItems;
    newListItems.push(text);
    console.log(newListItems);

    this.setState = ({
        listItems : newListItems
    });

}

此外,我在控制台中没有收到任何错误消息。

完整代码:



import React, { Component } from 'react';
import './App.css';
      
class ListItem extends Component{
  render(){
    return (<li>{this.props.title}</li>);
  }
}
     
class AddItem extends Component{

  handleClick(){
    this.props.addItem('blah');
  }

  render(){
    return (
      <div className="additem">
        <input type="text" className="newitemname"/>
        <span className="btn" onClick={this.handleClick.bind(this)}>Add item</span>
      </div>
    );
  }
}
    
    
class App extends Component {

  constructor(props){
    super(props);
    this.state = {
      listItems : ['Wash the dishes','Do the laundry','Something else']
    };
  }

  addItem(text){
    var newListItems = this.state.listItems;
    newListItems.push(text);
    console.log(newListItems);
    this.setState = ({
      listItems : newListItems
    });
  }

  render() {
    return (
      <div className="App">
        <ul>
          {this.state.listItems.map(function(item,index){
              return (
                  <ListItem key={index} title={item} />
              );
          })}
        </ul>
        <AddItem addItem={this.addItem.bind(this)} />
      </div>
    );
  }

}
    
    
export default App;
&#13;
&#13;
&#13;

1 个答案:

答案 0 :(得分:7)

问题是,您正在以错误的方式更新state,请使用此:

this.setState({
    listItems : newListItems
});

而不是:

this.setState = ({
    listItems : newListItems
});

<强>原因:

因为 setState 是一个函数而不是一个变量,我们需要调用它来更新状态值。

检查 this answer ,详细了解 setState behaviour

其他建议

当您为任何变量分配任何array时,变量只会获得array的引用,这意味着您将执行的所有更改将直接应用于原始array。并且直接改变state变量不是一个好主意,因此首先使用array创建slice的副本,然后使用push添加项目。像这样:

var newListItems = this.state.listItems.slice();
newListItems.push(text);
this.setState({
     listItems : newListItems
});

根据DOC

  

不要直接改变this.state,因为之后调用setState()可能   替换你所做的突变。把它当作状态对待   不可变的。

检查工作示例:

class ListItem extends React.Component{

  render(){
    return (<li>{this.props.title}</li>);
  }

}


class AddItem extends React.Component{

  handleClick(){
    this.props.addItem(this.item.value);
  }

  render(){
    return (
      <div className="additem">
        <input type="text" ref={item => this.item=item} className="newitemname"/>
        <span className="btn" onClick={this.handleClick.bind(this)}>Add item</span>
      </div>
    );
  }

}


class App extends React.Component {

  constructor(props){
    super(props);
    this.state = {
      listItems : ['Wash the dishes','Do the laundry','Something else']
    };
  }

  addItem(text){
    var newListItems = this.state.listItems.slice();
    newListItems.push(text);
    this.setState({
      listItems : newListItems
    });
  }

  render() {
    return (
      <div className="App">
        <ul>
          {this.state.listItems.map(function(item,index){
              return (
                  <ListItem key={index} title={item} />
              );
          })}
        </ul>
        <AddItem addItem={this.addItem.bind(this)} />
      </div>
    );
  }

}

ReactDOM.render(<App/>, document.getElementById('app'))
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

<div id='app' />