答案:
如果你尝试直接改变状态,那么组件将不会重新渲染。
// Wrong
this.state.message = 'Hello world'
正确方法应该是使用 setState( ) 方法。它调度组件状态对象的更新。当状态更改时,组件将会重新渲染。
// Correct
this.setState({ message: 'Hello World' })
另在React文档中,提到永远不要直接更改this.state,而是使用this.setState进行状态更新,这样做的两个主要原因如下: 1. setState分批工作:这意味着不能期望setState立即进行状态更新,这是一个异步操作,因此状态更改可能在以后的时间点发生,这意味着手动更改状态可能会被setState覆盖。 2. 性能:当使用纯组件或shouldComponentUpdate时,它们将使用===运算符进行浅表比较,但是如果更改状态,则对象引用将仍然相同,因此比较将失败。 为了避免避免数组/对象突变,可使用以下方法: 1)使用slice
let x = [‘a’, ’b’, ’c’, ’d’, ’e’]
// 如果要从上面的数组中删除c并打印该数组,可以执行以下操作。
x.splice(2,1)
console.log(x) // prints [‘a’, ’b’, ’d’, ’e’]
// 但是splice直接修改了x,因此它使数组变了。
// 如下所述,可以使用slice和concat来实现这一目标,因为它们是不可变的操作,
let x = [‘a’, ’b’, ’c’, ’d’, ’e’]
let y = x.slice(0,2).concat(x.slice(3))
console.log(x) // prints original array [‘a’, ’b’, ’c’, ’d’, ’e’]
console.log(y) // prints [‘a’, ’b’, ’d’, ’e’]
2)使用Object.assign
let x = { ‘a’:’Hello’, ‘b’: ‘Hey’ }
// 现在,假设我们要将“ a”的值从“ Hello”更改为“ Hurray”。
// 可变方式:
// x.a ='Hurray',如果x属于状态,这将直接在react中修改要避免的Object。
// 不变的方式:
let y = Object.assign({}, x } // creates a brand new object
// y.a ='Hurray',现在y可用于更新react state,因为这是完全不变的。
3)在ES6中使用Spread operator
// 使用spread operator可以实现与上述相同的功能。
let x = { ‘a’:’Hello’, ‘b’: ‘Hey’ }
let y = {…x,’a’:’Hurray’}
console.log(x) // prints { a: ‘Hello’, b: ‘Hey’ }
console.log(y)// prints { a: ‘Hurray’, b: ‘Hey’ }
4)嵌套对象 假设状态包含如下所示的用户对象,
let user = {
profile:{
address:{
city: ‘London’
}
}
}
如果要一成不变地将城市从伦敦更改为纽约,则需要执行以下操作
{
…state,
user:{
…state.user,
profile:{…state.user.profile,
address:{…state.user.profile.address, city:’Newyork’}}
}
}
这就是为什么建议保持react state尽可能平缓的原因,也可以考虑使用Immutable.js
它可以根据建议使用内置函数或Immutability Helper进行不可变数据修改在React docs中。