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

大家在用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方法进行render
    this.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,以免出现问题。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
VR(Virtual Reality)即虚拟现实,是一种可以创建和体验虚拟世界的计算机技术。它利用计算机生成一种模拟环境,是一种多源信息融合的、交互式的三维动态视景和实体行为的系统仿真,使用户沉浸到该环境中。VR技术通过模拟人的视觉、听觉、触觉等感觉器官功能,使人能够沉浸在计算机生成的虚拟境界中,并能够通过语言、手势等自然的方式与之进行实时交互,创建了一种适人化的多维信息空间。 VR技术具有以下主要特点: 沉浸感:用户感到作为主角存在于模拟环境中的真实程度。理想的模拟环境应该使用户难以分辨真假,使用户全身心地投入到计算机创建的三维虚拟环境中,该环境中的一切看上去是真的,听上去是真的,动起来是真的,甚至闻起来、尝起来等一切感觉都是真的,如同在现实世界中的感觉一样。 交互性:用户对模拟环境内物体的可操作程度和从环境得到反馈的自然程度(包括实时性)。例如,用户可以用手去直接抓取模拟环境中虚拟的物体,这时手有握着东西的感觉,并可以感觉物体的重量,视野中被抓的物体也能立刻随着手的移动而移动。 构想性:也称想象性,指用户沉浸在多维信息空间中,依靠自己的感知和认知能力获取知识,发挥主观能动性,寻求解答,形成新的概念。此概念不仅是指观念上或语言上的创意,而且可以是指对某些客观存在事物的创造性设想和安排。 VR技术可以应用于各个领域,如游戏、娱乐、教育、医疗、军事、房地产、工业仿真等。随着VR技术的不断发展,它正在改变人们的生活和工作方式,为人们带来全新的体验。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值