react的组件有一个非常烦的操作,就是【未经授权禁止转载】【版权所有,侵权必究】异步数据渲染。页面第一次打开的时候,会去【本文受版权保护】【未经授权禁止转载】mount所有的组件,但是,这个时候往往【版权所有】唐霜 www.tangshuang.net原创内容,盗版必究。都是没有数据的,特别是通过数据驱动的SP【原创不易,请尊重版权】原创内容,盗版必究。A。大部分的方案都是在component原创内容,盗版必究。【版权所有】唐霜 www.tangshuang.netDidMount中请求数据,得到数据后调转载请注明出处:www.tangshuang.net未经授权,禁止复制转载。用this.setState更新数据。这【版权所有,侵权必究】著作权归作者所有,禁止商业用途转载。个方案对于单个组件是没有问题的,但是,当【原创不易,请尊重版权】本文版权归作者所有,未经授权不得转载。数据来源不同,有一部分来自父组件,有一部【访问 www.tangshuang.net 获取更多精彩内容】【未经授权禁止转载】分来自自身,就比较麻烦。有这么一个场景,著作权归作者所有,禁止商业用途转载。原创内容,盗版必究。父组件请求完数据之后,调用自己的setS【未经授权禁止转载】转载请注明出处:www.tangshuang.nettate,导致子组件界面重新渲染了,子组转载请注明出处:www.tangshuang.net【原创不易,请尊重版权】件此时请求数据后也setState,导致【版权所有,侵权必究】转载请注明出处:www.tangshuang.net自己的界面重新渲染,这时没有父组件任何事原创内容,盗版必究。未经授权,禁止复制转载。。但是麻烦的事情接着来了,子组件自己请求【版权所有,侵权必究】【转载请注明来源】数据重新渲染之后,父组件再次请求数据,虽本文版权归作者所有,未经授权不得转载。【未经授权禁止转载】然父组件并没有修改子组件的props,但本文作者:唐霜,转载请注明出处。未经授权,禁止复制转载。还是导致子组件重新渲染,这时,子组件上一【未经授权禁止转载】【作者:唐霜】次请求的数据导致的渲染结果会被清空,整个原创内容,盗版必究。【作者:唐霜】子组件全部重绘了。实际上,我们希望保持子【版权所有】唐霜 www.tangshuang.net【访问 www.tangshuang.net 获取更多精彩内容】组件自己更新后的状态,并和父组件传来的p【版权所有】唐霜 www.tangshuang.net本文版权归作者所有,未经授权不得转载。rops有一个merge的过程。
【未经授权禁止转载】【访问 www.tangshuang.n著作权归作者所有,禁止商业用途转载。【关注微信公众号:wwwtangshuangnet】et 获取更多精彩内容】本文版权归作者所有,未经授权不得转载。【版权所有】唐霜 www.tangshu原创内容,盗版必究。著作权归作者所有,禁止商业用途转载。ang.net这种情况的大部分解决方案,是禁止子组件自本文作者:唐霜,转载请注明出处。未经授权,禁止复制转载。己请求数据,请求数据由父组件全权代理,通【原创不易,请尊重版权】【转载请注明来源】过父组件的setState更新子组件的p原创内容,盗版必究。【原创内容,转载请注明出处】rops,在子组件的componentW【转载请注明来源】【未经授权禁止转载】illReceiveProps中去更新子【访问 www.tangshuang.net 获取更多精彩内容】本文版权归作者所有,未经授权不得转载。组件的state来达到更新子组件的视图的未经授权,禁止复制转载。本文版权归作者所有,未经授权不得转载。目的。
未经授权,禁止复制转载。【作者:唐霜】【关注微信公众号:wwwtangshua未经授权,禁止复制转载。【本文首发于唐霜的博客】ngnet】但是,如果我不打算采用这个方案,那么该怎【关注微信公众号:wwwtangshuangnet】【访问 www.tangshuang.net 获取更多精彩内容】么办?
本文作者:唐霜,转载请注明出处。转载请注明出处:www.tangshua【版权所有】唐霜 www.tangshuang.net【版权所有,侵权必究】ng.net【转载请注明来源】还是有办法的,关键在于子组件的compo【版权所有,侵权必究】原创内容,盗版必究。nentWillReceiveProps【本文受版权保护】原创内容,盗版必究。和shouldComponentUpda本文版权归作者所有,未经授权不得转载。【访问 www.tangshuang.net 获取更多精彩内容】te。
未经授权,禁止复制转载。本文作者:唐霜,转载请注明出处。【本文首发于唐霜的博客】著作权归作者所有,禁止商业用途转载。第一个想法是只通过shouldCompo著作权归作者所有,禁止商业用途转载。【版权所有,侵权必究】nentUpdate进行控制:
本文版权归作者所有,未经授权不得转载。本文版权归作者所有,未经授权不得转载。【本文受版权保护】shouldComponentUpdate(nextProps, nextState) {
return !isEqual(nextProps, this.props) || !isEqual(nextState, this.state);
}
isEqual是lodash的方法。这样转载请注明出处:www.tangshuang.net未经授权,禁止复制转载。可以判断,当新的state和新的prop【未经授权禁止转载】【未经授权禁止转载】s有任何一个有变动时,才会更新界面。然而【作者:唐霜】【版权所有,侵权必究】,这需要开发者非常注意:
未经授权,禁止复制转载。未经授权,禁止复制转载。【原创内容,转载请注明出处】【作者:唐霜】1.绝对不能直接操作state,举个例子【未经授权禁止转载】【作者:唐霜】:
【版权所有】唐霜 www.tangshu【关注微信公众号:wwwtangshuangnet】未经授权,禁止复制转载。ang.net本文作者:唐霜,转载请注明出处。本文版权归作者所有,未经授权不得转载。【版权所有,侵权必究】let { items } = this.state
items.push(1)
this.setState({ items })
这个操作非常危险,看上去setState【未经授权禁止转载】著作权归作者所有,禁止商业用途转载。的操作是合法的,虽然你修改了state,著作权归作者所有,禁止商业用途转载。【原创不易,请尊重版权】但是你用新的是值去setState,然而原创内容,盗版必究。【作者:唐霜】,如果你这样操作,shouldCompo【版权所有】唐霜 www.tangshuang.net【本文受版权保护】nentUpdate中的nextStat未经授权,禁止复制转载。未经授权,禁止复制转载。e将会是被push了新值的state,判【访问 www.tangshuang.net 获取更多精彩内容】【作者:唐霜】断会错误。正确的做法是:
【访问 www.tangshuang.n【作者:唐霜】【原创内容,转载请注明出处】et 获取更多精彩内容】【作者:唐霜】本文版权归作者所有,未经授权不得转载。let { items } = this.state
items = items.concat(1)
this.setState({ items })
一定要用一个copy,而非直接修改sta转载请注明出处:www.tangshuang.net【作者:唐霜】te。
【转载请注明来源】【原创不易,请尊重版权】【访问 www.tangshuang.n本文版权归作者所有,未经授权不得转载。著作权归作者所有,禁止商业用途转载。et 获取更多精彩内容】2.不能在componentWillRe【作者:唐霜】【本文首发于唐霜的博客】ceiveProps中setState,本文版权归作者所有,未经授权不得转载。【未经授权禁止转载】在我的前面一篇文章里面说过,compon【原创内容,转载请注明出处】【访问 www.tangshuang.net 获取更多精彩内容】entWillReceiveProps内原创内容,盗版必究。原创内容,盗版必究。部的setState是同步的,会马上更新【版权所有】唐霜 www.tangshuang.net【原创内容,转载请注明出处】state而不触发重绘,所以,如果你在c【原创不易,请尊重版权】本文作者:唐霜,转载请注明出处。omponentWillReceiveP原创内容,盗版必究。转载请注明出处:www.tangshuang.netrops中setState,那么shou原创内容,盗版必究。【访问 www.tangshuang.net 获取更多精彩内容】ldComponentUpdate中的n【版权所有】唐霜 www.tangshuang.net【未经授权禁止转载】extState会是经过componen本文版权归作者所有,未经授权不得转载。【版权所有,侵权必究】tWillReceiveProps修改过【作者:唐霜】未经授权,禁止复制转载。的。
【转载请注明来源】【版权所有】唐霜 www.tangshu【版权所有】唐霜 www.tangshuang.net【本文首发于唐霜的博客】ang.net转载请注明出处:www.tangshua【原创内容,转载请注明出处】【原创内容,转载请注明出处】ng.net第1个问题是可以避免的,在万不得已的情况著作权归作者所有,禁止商业用途转载。【转载请注明来源】下,我们甚至可以动用lodash.clo转载请注明出处:www.tangshuang.net原创内容,盗版必究。neDeep,但是第2个问题,我们需要谨著作权归作者所有,禁止商业用途转载。未经授权,禁止复制转载。慎处理,因为我们不可能不在compone【本文首发于唐霜的博客】【转载请注明来源】ntWillReceiveProps中调本文作者:唐霜,转载请注明出处。【访问 www.tangshuang.net 获取更多精彩内容】用setState,这时不可能的,我们异本文版权归作者所有,未经授权不得转载。【版权所有,侵权必究】步数据处理方案只能这样去做。那么怎么解决原创内容,盗版必究。未经授权,禁止复制转载。这个问题呢?
【原创内容,转载请注明出处】转载请注明出处:www.tangshua本文版权归作者所有,未经授权不得转载。【访问 www.tangshuang.net 获取更多精彩内容】ng.net著作权归作者所有,禁止商业用途转载。【原创内容,转载请注明出处】那就是,在componentWillRe本文作者:唐霜,转载请注明出处。转载请注明出处:www.tangshuang.netceiveProps中做进一步判断,是否【版权所有】唐霜 www.tangshuang.net【版权所有,侵权必究】要更新setState,大部分情况下,如著作权归作者所有,禁止商业用途转载。【版权所有】唐霜 www.tangshuang.net果父组件虽然重绘,但是传给子组件的pro转载请注明出处:www.tangshuang.net著作权归作者所有,禁止商业用途转载。ps不变的话,这个子组件不需要重绘,所以著作权归作者所有,禁止商业用途转载。【版权所有】唐霜 www.tangshuang.net,在componentWillRecei【本文受版权保护】【原创不易,请尊重版权】veProps中也加入一个判断:
【转载请注明来源】【访问 www.tangshuang.n未经授权,禁止复制转载。【本文首发于唐霜的博客】et 获取更多精彩内容】【本文首发于唐霜的博客】未经授权,禁止复制转载。componentWillReceiveProps(nextProps) {
if (isEqual(this.props, nextProps)) {
return
}
// ...
this.setState({ ... })
}
shouldComponentUpdate(nextProps, nextState) {
return !isEqual(nextProps, this.props) || !isEqual(nextState, this.state);
}
这样的处理就极为巧妙了。当父组件传给子组【本文首发于唐霜的博客】【转载请注明来源】件的props发生变化时,子组件整个重置著作权归作者所有,禁止商业用途转载。【原创内容,转载请注明出处】,用新的props重绘(之前的setSt【原创内容,转载请注明出处】未经授权,禁止复制转载。ate造成的改动被重置),而如果父组件传转载请注明出处:www.tangshuang.net未经授权,禁止复制转载。的props不变时,就不进行任何动作。
【本文受版权保护】未经授权,禁止复制转载。这个问题,带来了react组件的另外一个【原创内容,转载请注明出处】【版权所有】唐霜 www.tangshuang.net思考,如果我们的大部分组件都是依赖异步数转载请注明出处:www.tangshuang.net转载请注明出处:www.tangshuang.net据的,那么组件的生命周期是不是存在问题?未经授权,禁止复制转载。【版权所有】唐霜 www.tangshuang.netcomponentDidMount的意义原创内容,盗版必究。著作权归作者所有,禁止商业用途转载。何在呢?难道仅仅是绑定一些事件之类的?
本文版权归作者所有,未经授权不得转载。【作者:唐霜】

哈喽,看到你这篇文章写得蛮清楚的,我遇到了一个类似的问题,想请教一下~
当我在来回快速切换菜单的时候,每个菜单didmount的时候都分别请求各自的数据,我在上一个请求没有完成时,就手动点了下一个菜单,这时先先展现了菜单B,而后菜单A的响应完成后,又重新渲染了菜单A的view,导致我真正想要看的菜单B的view没有被渲染,请问你对这个问题有了解嘛~
(PS: 446875622 这是我的微信号,方便的话可以加我一下,我仔细请教,麻烦了~)
deferer-queue了解一下 https://www.tangshuang.net/6092.html
好的,蟹蟹~