根据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'}
}))