setState无法更新状态:ReactJS

5
我觉得我尝试了太阳底下的一切,但肯定漏掉了什么非常明显的东西。在下面的addItem()函数中,我试图将一个新项目推入数组并更新状态,但无论我做什么,状态都不会从初始数组改变。
当我用console.log newListItems时,新项目包含在内,所以到那个步骤为止的一切都有效,只是实际状态不会更新。我漏掉了什么?
加项目的方法:
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;

1个回答

7
问题在于,您以错误的方式更新了state,请使用以下代码进行更新:
this.setState({
    listItems : newListItems
});

不要这样做:

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

原因:

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

查看这个答案以获取有关setState行为的更多详细信息。

其他建议:

当您将任何array分配给任何变量时,变量只会获取array的引用,这意味着您进行的所有更改都将直接应用于原始array。直接更改state变量并非明智之举,因此请使用slice创建数组的副本,然后使用push将项目添加到其中。像这样:

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

根据文档

不要直接修改this.state,因为调用setState()之后可能会替换您所做的更改。将this.state视为不可变的。

请查看工作示例:

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' />


天啊,一个等号让我抓狂了一个小时!感谢你的指出! - MyNotes
如果有人切换到纯渲染,我还会在var newListItems = this.state.listItems之后添加一个slice()调用。 - Sulthan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接