大家在用react的时候,应该都知道react的state更新会由父到子逐级更新的事情,那么就会有这样一个问题,当要渲染的页面元素较多,极端情况下,特别是大数据展示的时候,由顶层一点点逐级渲染,性能消耗太大。打个具体点的比方,有A,B,C三个组件,A是B,C的父组件,当应用场景是,B的某个动作需要C来相应的时候,传统的做法如下。

class A extends React.Component {constructor(props) {super(props)this.state = {X: "",}}onChangeX=(v)=>{this.setState({X:v})}render() {return <div><B onChangeX={this.onChangeX}/><C X={this.state.X}/></div>}
}class B extends React.Component {render() {return <div onClick={this.props.onChangeX}>{sample}</div>}
}
class C extends React.Component {render() {return <div>{this.props.X}</div>}
}

在这种代码的实现下,由B触发的事件必须经过父组件A所缓存的状态才能更新到C,如果A本身Render的性能消耗大的话,比如A本身有很多的逻辑计算 或者A下面还有其它组件D,E,F,G,画面渲染就非常耗时。那么有没有什么办法让B触发,绕过父组件A只更新目标C呢。

本人这里有两个方案可供选择。

第一,走redux

让触发点B不直接调用A的内部方法,而是发送redux更新用的Action。同时在被渲染的C组件外层包裹一个直接接收redux数据的container,数据由redux传给C。关于redux和container就暂时不写入代码了(偷个懒)

class A extends React.Component {constructor(props) {super(props)this.state = {}}render() {return <div><B/><C/></div>}
}class B extends React.Component {render() {return <div onClick={this.props.onChangeXAction}>{sample}</div>}
}
class C extends React.Component {render() {return <div>{this.props.X}</div>}
}

这个方法的好处是,条理清晰,代码好读。坏处是副作用太大,首先是当组件存在于一个比较大的应用的时候,redux的负担过重,影响反应时间。其次是要想达到不触发父组件A的目的,A本身就不能跟redux关联,否则,redux的状态动了,在没有特殊控制的情况下,A也会被触发更新。

第二个方法,把被渲染组件C的this传给A,然后缓存下来。当被触发的时候调用C自身的setState方法更新。代码如下:

class A extends React.Component {constructor(props) {super(props)this.state = {// 组件C的对象缓存cInst: "",}}setCInst=(inst)=>{// 给缓存赋值this.setState({cInst:inst})}onChangeX=(v)=>{//由C自身对象的setState方法进行renderthis.cInst.setState({X:v})}render() {return <div><B onChangeX={this.onChangeX}/><C setCInst={this.setCInst}/></div>}
}class B extends React.Component {render() {return <div onClick={this.props.onChangeX}>{sample}</div>}
}
class C extends React.Component {constructor(props) {super(props)this.state = {X: "",}}componentDidMount() {this.props.setCInst(this)}render() {return <div>{this.state.X}</div>}
}

这样一来,当B开始触发的时候,因为没有调用A的setstate方法,A就不会重新渲染,从而达到提高性能的目的。当然,这种方法也有缺点,C组件的缓存是在componentDidMount生命周期上挂载的,那么在写父组件的时候就要特别小心。比如本人在另一篇文章中【getDerivedStateFromProps 如何区分状态更新来源】

闫松:react -- getDerivedStateFromProps 如何区分状态更新来源​zhuanlan.zhihu.com

之中写到的方法,用随机标志位来判断区分跟新元,就不适用上面的代码。原因是,当给子组件C加上key=随机标志位 之后。每次A在渲染的时候,都会生成新的key。当新key生成的时候,react认为以前的子组件已经被抛弃了。会生成新的子组件,这时候新的子组件会重新执行componentDidMount生命周期,而建立缓存的时候,父组件又会重新render。这样就会出现死循环。所以,当用以上方法时,切记不要加key或者加固定key,以免出现问题。

react循环setstate_react -- 关于兄弟组件触发更新的问题相关推荐

  1. React开发(208):react代码分割在嵌套组件中更新 Context

  2. React兄弟组件之间通信

    兄弟组件之间通信 React是只有单项数据流动模式,也就是只能父组件的数据传递给子组件,而没有办法将子组件的数据传递给父组件.那么如果想要两个子兄弟组件通信该怎么办呢? 答案是可以通过子组件向父组件推 ...

  3. React组件进阶--组件通讯介绍,组件的 props特点,组件通讯的三种方式子到父,父到子,兄弟到兄弟组件,Context,回顾练习

    1.组件通讯介绍 组件是独立且封闭的单元,默认情况下,只能使用组件自己的数据(state). 在组件化过程中,我们将一个完整的功能 拆分成多个组件,以更好的完成整个应用的功能. 而在这个过程中,多个组 ...

  4. vue 渲染函数处理slot_面试官:Vue 和 React 对于组件的更新粒度有什么区别?

    前言 我们都知道 Vue 对于响应式属性的更新,只会精确更新依赖收集的当前组件,而不会递归的去更新子组件,这也是它性能强大的原因之一. 例子 举例来说 这样的一个组件: <div> {{ ...

  5. 从一个表格render方法问题看React函数组件的更新

    从一个表格render方法问题看React函数组件的更新 最近在开发中碰到了一个现象觉得很有典型能作为例子所以给大家分享一下,从这个现象我们能很清楚的看到函数组件的更新的特点,以及我们应该如何去理解和 ...

  6. React(5)React兄弟组件之间的通信

    文章目录 前言 一.兄弟组件之间的通信原理 二.三个组件的基本结构 1.子组件ColorSelector的基本结构 2.子组件ColorBoard的基本结构 3.父组件Color的基本结构 三.Col ...

  7. React redux 兄弟组件之间通信

    做项目的时候遇到一个场景,兄弟组件A和B,在组件B中的点击事件里面需要操作A组件的state,进行A组件里的tab标签增加和删除.因为用到redux,所以需要把这个state的数据抽出来做状态管理,随 ...

  8. React组件通信传值 父传子 子传父 兄弟组件传值

    一.父组件传递子组件 在父组件中引入子组件,将父组件的state值放到子组件标签中传递,在子组件中用this.props.传值名称,接收 父组件代码: import React, { Componen ...

  9. vue组件通信v兄弟组件通信eventbus遇到的问题(多次触发、第一次不触发)

    组件通讯包括:父子组件间的通信和兄弟组件间的通信.在组件化系统构建中,组件间通信必不可少的 (vuex以后再说). 父组件--> 子组件 1. 属性设置 父组件关键代码如下: 1 <tem ...

最新文章

  1. 业务库负载翻了百倍,我做了什么来拯救MySQL架构?
  2. java方法生命周期_Java线程的第二种实现方式以及生命周期
  3. java改写weka中的算法_用Eclipse在Weka中嵌入新算法
  4. 玩转ceph性能测试---对象存储(一)
  5. Android开发之蓝牙(Bluetooth)---源码目录
  6. 如何在Spring容器中加载自定义的配置文件
  7. Codeforces Round #102 (Div. 1) D Help Shrek and Donkey 2
  8. 线性渐变和放射性渐变
  9. 各类曲线的参数方程_常见曲线的参数方程
  10. PuTTYgen使用教程
  11. jq ui-selectable中click单击事件,dblclick双击事件无效
  12. cubemx配置usb
  13. 如何改变B站视频播放速度
  14. 大学计算机应用基础第二版习题答案,《大学计算机应用基础》各章习题参考答案...
  15. 计算机常用英语词汇一览表,计算机常用英语词汇总表
  16. 奉子成婚,永远不可能成为潮流
  17. 西电 计算机学院 博后流动站,西电7个博士后科研流动站接受专家组综合评估检查...
  18. pdfsam Enhanced 6中文版
  19. html背景图片带边框,css 使用background背景实现border边框效果
  20. 简单明了实现Java地图小程序项目

热门文章

  1. oracle体系结构剖析
  2. linux下防火墙加白名单
  3. find -exec 与xargs 区别
  4. pycharm ssh mysql_PyCharm使用之配置SSH Interpreter的方法步骤
  5. 调用bash shell脚本的方式
  6. bat批处理删除指定N天前的文件
  7. Vue + VueRouter + Vuex + Axios 抓取 GitHub 上的 Issues 来搭建个人博客站点
  8. HDU 4944 逆序数对
  9. 牛逼!Redis 的字符串是这样实现的…
  10. 从零开发一个 Java Web 项目要点