react改变state必须知道的知识点

  react可以通过this.state.xx的方式直接获取state,但是当我们修改state的时候,往往有许多的坑。

  1. 不能直接修改state
    组件修改state,并不会重新触发render。例如:
 //错误
this.state.title='attend';

//正确
this.setState({title:'attend'});
  1. state的更新是异步的
      调用setState时,组件state并不会立即改变,只是把要修改的状态放入事件队列当中,react会优化真正的执行时机,如果连续写多次setState,会将多次setState的状态修改合并成一次状态修改。
//正确
this.setState((prevState, props)=>({
counter: prevState.counter + 1
}))
  1. state的更新是一个合并的过程
      当调用setState()修改组件的状态时,只需要传入发生改变的state,而不是完整的state,因为组件state的更新是一个合并的过程:
this.state = {
title: 'React',
content: 'React is an wondeful JS library'
}

  当只需要修改title时,只需要将修改的title传给setState即可:

this.setState({title:'ReactJs'});

  react会合并最新的title到原来的状态,同时保留原来状态的content,最终合并state为:

this.state = {
title: 'ReactJs',
content: 'React is an wondeful Js library'
}

state与不可变对象
  react官方把state当成不可变对象,一方面直接修改this.state,组件并不会重新render;另一方面,state中包含的所有状态都应该是不可变的对象,state当中的某一个状态发生变化时,应该重新创建这个状态对象,而不是直接修改原来的state状态,那么当状态发生变化时,如何去创建新的状态呢,我们根据状态类型可以分为下面三种情况:

  1. 状态类型为不可变类型
    number、string、boolean、null、undefined
    这种情况最简单,因为状态是不可变类型,所以直接给要修改的状态赋一个新值即可,例如我们要修改的count为number型,title(string),success(boolean)三个状态:
this.setState({
count:1,
title:'React',
success:true
})
  1. 状态类型为数组
    假如有一个数组类型的状态books,当向books中增加一本书时。
//方法一:使用preState,concat创建新数组
 this.setState((prevState)=>({
books: prevState.books.concat(['React Guide'])
}))

//方法二:ES6 spread syntax
this.setState(prevState=>({
books:[...prevState,'React Guide']
}))

当我们从books中截取部分元素作为新状态时,可以用数组的slice方法:

this.setState(prevState=>({
books: prevState.books.slice(1,3);
}))

当从books中过滤部分元素后,作为新状态时,可以使用filter方法:

this.setState(prevState=>({
books: prevState.books.filter(item=>{
  return item!='React';
})
}))

【注意】不要使用push,pop,shift,unshift,splice等方法修改数组类型的状态,因为这些方法都是在原数组的基础上修改的,而concat,slice,filter会返回一个新的数组。

  1. 状态的类型是普通对象
    使用es6的Object.assgin()方法
this.setState({
onwer: Object.assgin({},preState.onwer,{name:'Jason'});
})

(2) 使用对象扩展语法(Object spread properties):

this.setState(preState=>{
owner: {...preState.owner, name:'Jason'}
})

总结
  创建新的状态的关键是,避免使用直接修改原对象的方法,这种方法在vue中称为变异方法,而是使用可以返回一个新对象的方法,当然可以使用Immutable的JS库(Immutable.js)实现类似的效果。

思考

为什么React推荐组件状态的修改时不可变对象呢?
(1) 不可变对象的修改会返回一个新的对象,不用担心原对象在不小心的情况下修改导致的错误,方便程序的管理和调试。
(2) 处于性能的考虑,对象组件的状态时不可变对象时,在组件的shouldComponentUpdate方法中仅需要比较前后两次状态对象的引用就可以判断状态是否真的改变,从而避免不必要的render调用。

进阶
  除了以上方法改变react组件的状态之外,我们还经常会用到replaceState()改变组件的状态。
  replaceState()方法与setState()类似,但是方法只会保留nextState中状态,原state不在nextState中的状态都会被删除。

//使用语法:
replaceState(object nextState[, function callback])
nextState,将要设置的新状态,该状态会替换当前的state。
callback,可选参数,回调函数。该函数会在replaceState设置成功,且组件重新渲染后调用。
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 作为一个合格的开发者,不要只满足于编写了可以运行的代码。而要了解代码背后的工作原理;不要只满足于自己的程序...
    六个周阅读 12,696评论 1 33
  • 说在前面 关于 react 的总结过去半年就一直碎碎念着要搞起来,各(wo)种(tai)原(lan)因(le)。心...
    陈嘻嘻啊阅读 11,813评论 7 41
  • 第三十五章 偷得一日闲,山中寻幽静 今天己经是6月2日了,昨天把孩子的准考证打印出来了,考点是青岛二中,是...
    韬乐阅读 3,813评论 0 4
  • 文/归海无期 妈妈说每一个人都是 夜空中闪亮的星星 可谁又知道遥远的夜空 多么空旷多么寒冷 地面上奔跑的孩子啊 挤...
    归海无期阅读 1,216评论 0 0
  • 九月初,听说办公室要来一位新人。 因为忙于下场子,我们甚至都来不及想来了新人办公室怎么再重新布置。 ...
    槑头槑脑儿阅读 3,130评论 0 1

友情链接更多精彩内容