根据State类型 更新
当状态发生变化时,如何创建新的状态?根据状态的类型,可以分成三种情况:
1、 状态的类型是不可变类型(数字,字符串,布尔值,null, undefined)
这种情况最简单,直接给要修改的状态赋一个新值即可
//原state
this.state = {
count: 0,
title : 'React',
success:false
}
//改变state
this.setState({
count: 1,
title: 'bty',
success: true
})
2、 状态的类型是数组
数组是一个引用,React 执行 diff 算法时比较的是两个引用,而不是引用的对象。所以直接修改原对象,引用值不发生改变的话,React 不会重新渲染。因此,修改状态的数组或对象时,要返回一个新的数组或对象。
(1)增加
如有一个数组类型的状态books,当向books中增加一本书(chinese)时,使用数组的concat方法或ES6的数组扩展语法
// 方法一:将state先赋值给另外的变量,然后使用concat创建新数组
let books = this.state.books;
this.setState({
books: books.concat(['chinese'])
})
// 方法二:使用preState、concat创建新数组
this.setState(preState => ({
books: preState.books.concat(['chinese'])
}))
// 方法三:ES6 spread syntax
this.setState(preState => ({
books: [...preState.books, 'chinese']
}))
(2)截取
当从books中截取部分元素作为新状态时,使用数组的slice方法:
// 方法一:将state先赋值给另外的变量,然后使用slice创建新数组
let books = this.state.books;
this.setState({
books: books.slice(1,3)
})
//
// 方法二:使用preState、slice创建新数组
this.setState(preState => ({
books: preState.books.slice(1,3)
}))
(3)条件过滤
当从books中过滤部分元素后,作为新状态时,使用数组的filter方法:
// 方法一:将state先赋值给另外的变量,然后使用filter创建新数组
var books = this.state.books;
this.setState({
books: books.filter(item => {
return item != 'React';
})
})
// 方法二:使用preState、filter创建新数组
this.setState(preState => ({
books: preState.books.filter(item => {
return item != 'React';
})
}))
注意:不要使用push、pop、shift、unshift、splice等方法修改数组类型的状态,因为这些方法都是在原数组的基础上修改,而concat、slice、filter会返回一个新的数组。
3、状态的类型是普通对象(不包含字符串、数组)
对象是一个引用,React 执行 diff 算法时比较的是两个引用,而不是引用的对象。所以直接修改原对象,引用值不发生改变的话,React 不会重新渲染。因此,修改状态的数组或对象时,要返回一个新的对象。
使用ES6 的Object.assgin方法
// 方法一:将state先赋值给另外的变量,然后使用Object.assign创建新对象
var owner = this.state.owner;
this.setState({
owner: Object.assign({}, owner, {name: 'Jason'})
})
// 方法二:使用preState、Object.assign创建新对象
this.setState(preState => ({
owner: Object.assign({}, preState.owner, {name: 'Jason'})
}))
使用对象扩展语法(object spread properties)
// 方法一:将state先赋值给另外的变量,然后使用对象扩展语法创建新对象
var owner = this.state.owner;
this.setState({
owner: {...owner, name: 'Jason'}
})
// 方法二:使用preState、对象扩展语法创建新对象
this.setState(preState => ({
owner: {...preState.owner, name: 'Jason'}
}))