Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >React16的memo函数有啥用

React16的memo函数有啥用

原创
作者头像
挥刀北上
修改于 2020-08-18 10:13:32
修改于 2020-08-18 10:13:32
1.2K00
代码可运行
举报
文章被收录于专栏:Node.js开发Node.js开发
运行总次数:0
代码可运行

React16的memo和PureComponent作用类似,只不过前者只适用于函数组件,后者适应于类组件。

关于两者的作用,我们先从PureComponent说起,在了解PureComponent之前要先了解shouldComponentUpdate函数,在类组件中有一个叫做shouldComponentUpdate的生命周期函数,这个函数可以通过返回true或false来决定当前组件是否重新渲染。

而PureComponent自带shouldComponentUpdate函数,PureComponent自带的shouldComponentUpdate函数会在当前组件的props或者state发生变化时,对props或者state进行浅对比,如果相同则不进行重新渲染,反之则会进行渲染。

说到这里来了解一下浅对比,啥叫浅对比呢,类似于浅拷贝,具体的内容大家可以去百度,这里不做赘述,只做简单说明,举个例子,看代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import React,{memo} from "react";
import ReactDOM from 'react-dom';
class CommentList extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      commentList: [{
        body: '大三岁', author: '张三'
      }, {
        body: '新冠病毒', author: '李四'
      }]
    }
  }

  componentWillMount() {
    setTimeout(() => {
      this.setState((prevState, props) => {
        return {
          commentList: [{
            body: '大三岁', author: '张三'
          }, {
              body: '新冠1病毒', author: '李四'
          }]
        }
      })
    }, 1000)
  }

  render() {
    return (
      <div>
        {
          this.state.commentList.map((item, index) => {
            return <Comment {...item} key={index} />
          })
        }
      </div>
    )

  }
}
function Comment(props) {
  console.log('渲染了', props)
  return <div>
    <p>{props.body}</p>
    <p>{props.author}</p>
    <p>{props.arr.length}</p>
  </div>
}

阅读源码,我们定义了两个组件,CommentList组件与Comment组件,CommentList组件内部的state是一个数组,每条数据用Comment来渲染。我们在componentWillMount设置定时器模拟数据发生变化,我们看到第二条数据的body发生变化了,所以对应的comment组件应该重新渲染,但是我们发现所有Comment组件都重新渲染了。这不利于我们页面的性能优化,咋办呢?

此时我们可以借助memo或者PureComponent来实现只让该渲染的组件渲染,啥是该渲染的组件呢?那就是props或者state发生变化的组件,那变化的标准是怎么样的呢?

来看代码,用memo来实现:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import React,{memo} from "react";
import ReactDOM from 'react-dom';
class CommentList extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      commentList: [{
        body: '大三岁', author: '张三' 
      }, {
        body: '新冠病毒', author: '李四' 
      }]
    }
  }

  componentWillMount() {
    setTimeout(() => {
      this.setState((prevState, props) => {
        return {
          commentList: [{
            body: '大三岁', author: '张三'
          }, {
              body: '新冠1病毒', author: '李四'
          }]
        }
      })
    }, 1000)
  }

  render() {
    return (
      <div>
        {
          this.state.commentList.map((item, index) => {
            return <Comment {...item} key={index} />
          })
        }
      </div>
    )

  }
}



function Comment(props) {
  console.log('渲染了', props)
  return <div>
    <p>{props.body}</p>
    <p>{props.author}</p>
    <p>{props.arr.length}</p>
  </div>
}

// 第一种方式 用memo包裹函数组件
Comment = memo(Comment)

用PureComponent来实现:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import React,{memo} from "react";
import ReactDOM from 'react-dom';
class CommentList extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      commentList: [{
        body: '大三岁', author: '张三' 
      }, {
        body: '新冠病毒', author: '李四' 
      }]
    }
  }

  componentWillMount() {
    setTimeout(() => {
      this.setState((prevState, props) => {
        return {
          commentList: [{
            body: '大三岁', author: '张三'
          }, {
              body: '新冠1病毒', author: '李四'
          }]
        }
      })
    }, 1000)
  }

  render() {
    return (
      <div>
        {
          this.state.commentList.map((item, index) => {
            return <Comment {...item} key={index} />
          })
        }
      </div>
    )

  }
}

class Comment extends React.PureComponent {
  constructor() {
    super()
  }
  render() {
    console.log('渲染了')
    const props = this.props
    return <div>
      <p>{props.body}</p>
      <p>{props.author}</p>
    </div>
  }
}

阅读源码,我们分别用memo和PureComponent改造了代码,并且运行的话,只有该渲染的组件发生了渲染。

渲染的组件前后的props发生变化的组件才会重新渲染,来看一下props或者state发生变化的标准:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
{body: '新冠病毒', author: '李四'} 

{body: '新冠1病毒', author: '李四'} 

上面两个对象进行浅对比body发生变化,所以会渲染,而另一个组件数据没变所以没有重新渲染,从而提高了页面性能。

以上便是memo的作用了,但是这里有一个问题,那就是如果props中的某一个属性是引用数据类型,这个引用数据发生改变,但是引用未变,组件是不会重新渲染的,首先我们看下不使用memo的代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import React,{memo} from "react";
import ReactDOM from 'react-dom';
class CommentList extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      commentList: [{
        body: '大三岁', author: '张三',arr:[]
      }, {
        body: '新冠病毒', author: '李四',arr:[]
      }]
    }
  }

  componentWillMount() {
    setTimeout(() => {
      this.state.commentList[0].arr.push(999)
      this.setState({ commentList: this.state.commentList})
    }, 1000)
  }

  render() {
    return (
      <div>
        {
          this.state.commentList.map((item, index) => {
            return <Comment {...item} key={index} />
          })
        }
      </div>
    )

  }
}

// 

function Comment(props) {
  console.log('渲染了', props)
  return <div>
    <p>{props.body}</p>
    <p>{props.author}</p>
    <p>{props.arr.length}</p>
  </div>
}

上面的代码,我们没有使用memo,Comment的props发生变化后,所有的Comment组件都重新渲染了,如图:

效果截图
效果截图

上图红框处显示了组件重新渲染了,然后我们用memo改造代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import React,{memo} from "react";
import ReactDOM from 'react-dom';
class CommentList extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      commentList: [{
        body: '大三岁', author: '张三',arr:[]
      }, {
        body: '新冠病毒', author: '李四',arr:[]
      }]
    }
  }

  componentWillMount() {
    setTimeout(() => {
      this.state.commentList[0].arr.push(999)
      this.setState({ commentList: this.state.commentList})
    }, 1000)
  }

  render() {
    return (
      <div>
        {
          this.state.commentList.map((item, index) => {
            return <Comment {...item} key={index} />
          })
        }
      </div>
    )

  }
}

// 

function Comment(props) {
  console.log('渲染了', props)
  return <div>
    <p>{props.body}</p>
    <p>{props.author}</p>
    <p>{props.arr.length}</p>
  </div>
}


Comment = memo(Comment)

此时看效果:

效果截图
效果截图

上图展示显示了,虽然组件的props发生了变化,但是组件为重新渲染。

那这个bug怎么解决呢,很简单,不要直接修改完数据直接使用,而是修改完后深拷贝一下再去调用setState。

所以在使用memo和PureComponent时大家需要特别注意,总结一下:

1、memo和PureComponent的作用提高渲染性能,避免不必要的渲染。

2、memo和PureComponent的原理是通过浅拷贝来实现的。

3、通过案例演示了memo的作用。

4、memo的缺点,当props或state中的属性有引用属性时需要注意,修改完成后进行一下深拷贝在调用setState。

以上便是使用memo的一下注意事项,希望对你有所帮助。

参考:你真的了解浅比较么?

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
【RL Base】强化学习核心算法:深度Q网络(DQN)算法
深度Q网络(DQN)是深度强化学习的核心算法之一,由Google DeepMind在2015年的论文《Playing Atari with Deep Reinforcement Learning》中提出。DQN通过结合深度学习和强化学习,利用神经网络近似Q值函数,在高维、连续状态空间的环境中表现出了强大的能力。
不去幼儿园
2024/12/03
4510
【RL Base】强化学习核心算法:深度Q网络(DQN)算法
《Scikit-Learn与TensorFlow机器学习实用指南》 第16章 强化学习(上)
强化学习(RL)如今是机器学习的一大令人激动的领域,当然之前也是。自从 1950 年被发明出来后,它在这些年产生了一些有趣的应用,尤其是在游戏(例如 TD-Gammon,一个西洋双陆棋程序)和机器控制领域,但是从未弄出什么大新闻。直到 2013 年一个革命性的发展:来自英国的研究者发起了Deepmind 项目,这个项目可以学习去玩任何从头开始的 Atari 游戏,在多数游戏中,比人类玩的还好,它仅使用像素作为输入而没有使用游戏规则的任何先验知识。这是一系列令人惊叹的壮举中的第一个,并在 2016 年 3 月以他们的系统阿尔法狗战胜了世界围棋冠军李世石而告终。从未有程序能勉强打败这个游戏的大师,更不用说世界冠军了。今天,RL 的整个领域正在沸腾着新的想法,其都具有广泛的应用范围。DeepMind 在 2014 被谷歌以超过 5 亿美元收购。
SeanCheney
2018/12/17
5110
《Scikit-Learn与TensorFlow机器学习实用指南》 第16章 强化学习(上)
Python 强化学习实用指南:6~10
在前面的章节中,我们学习了强化学习(RL)的基本概念和几种 RL 算法,以及如何将 RL 问题建模为马尔可夫决策过程(MDP)。 我们还看到了用于解决 MDP 的不同的基于模型和无模型的算法。 在本章中,我们将看到 RL 中的经典问题之一,称为多臂老虎机(MAB)问题。 我们将看到什么是 MAB 问题,以及如何使用不同的算法解决该问题,然后了解如何使用 MAB 识别将接收大部分点击的正确广告横幅。 我们还将学习广泛用于构建推荐系统的上下文老虎机。
ApacheCN_飞龙
2023/04/24
1.5K0
《Scikit-Learn与TensorFlow机器学习实用指南》 第16章 强化学习(下)
在二十世纪初,数学家 Andrey Markov 研究了没有记忆的随机过程,称为马尔可夫链。这样的过程具有固定数量的状态,并且在每个步骤中随机地从一个状态演化到另一个状态。它从状态S演变为状态S'的概率是固定的,它只依赖于(S, S')对,而不是依赖于过去的状态(系统没有记忆)。
SeanCheney
2018/12/17
6100
《Scikit-Learn与TensorFlow机器学习实用指南》 第16章 强化学习(下)
【机器学习】突出强化学习中智能体通过与环境交互不断成长,其决策能力逐步进化提升,展现强化学习核心特点与动态过程。
在强化学习中,智能体是能够感知环境并采取行动的实体,而环境则是智能体所处的外部世界,智能体与环境之间通过交互来实现学习过程。例如,在一个简单的迷宫游戏中,智能体可以是一个试图找到出口的虚拟角色,而迷宫及其内部的障碍物、出口等构成了环境。
逆向-落叶
2024/12/25
3150
【机器学习】突出强化学习中智能体通过与环境交互不断成长,其决策能力逐步进化提升,展现强化学习核心特点与动态过程。
深度学习算法(第34期)----强化学习之梯度策略实现
上期我们一起学习了强化学习中OpenAI中平衡车的相关环境以及搭建神经网络策略的相关知识, 深度学习算法(第33期)----强化学习之神经网络策略学习平衡车 今天我们学习强化学习中行为评价和梯度策略的相关知识。
智能算法
2019/11/04
8110
深度学习算法(第34期)----强化学习之梯度策略实现
使用PyTorch Lightning构建轻量化强化学习DQN(附完整源码)
本文旨在探究将PyTorch Lightning应用于激动人心的强化学习(RL)领域。在这里,我们将使用经典的倒立摆gym环境来构建一个标准的深度Q网络(DQN)模型,以说明如何开始使用Lightning来构建RL模型。
deephub
2020/05/09
1.9K0
使用PyTorch Lightning构建轻量化强化学习DQN(附完整源码)
Python 强化学习实用指南:1~5
强化学习(RL)是机器学习的一个分支,其中学习是通过与环境交互来进行的。 这是面向目标的学习,不教导学习器采取什么行动; 相反,学习器从其行动的结果中学习。 随着各种算法的迅速发展,它是人工智能(AI)中最活跃的研究领域之一。
ApacheCN_飞龙
2023/04/24
1.9K0
【RL】基于迁移学习的强化学习(RL-TL)算法
基于迁移学习的强化学习(Reinforcement Learning with Transfer Learning,简称 RL-TL)是将迁移学习(Transfer Learning)的概念应用于强化学习(Reinforcement Learning,简称 RL)中的一种方法。其核心思想是在强化学习的环境中,利用已有的经验或在其他任务中学到的知识来提升学习效率和表现。这样可以减少从零开始学习的时间和样本需求,尤其在数据稀缺或任务复杂的场景中。
不去幼儿园
2024/12/03
1970
【RL】基于迁移学习的强化学习(RL-TL)算法
【机器学习】机器学习重要分支——强化学习:从理论到实践
强化学习(Reinforcement Learning, RL)作为机器学习的重要分支之一,通过与环境交互、试错学习来优化决策策略,已在机器人控制、游戏AI、自动驾驶等领域展现出巨大的潜力。本文将深入探讨强化学习的基本原理、核心算法及其在实际中的应用,并提供代码示例和图表以帮助读者更好地理解和掌握这一技术。
E绵绵
2024/06/17
1.5K0
Python 强化学习实用指南:11~14
在最后三章中,我们学习了各种深度强化学习算法,例如深度 Q 网络(DQN),深度循环 Q 网络(DRQN)和异步优势演员评论家(A3C)网络。 在所有算法中,我们的目标是找到正确的策略,以便我们能够最大化回报。 我们使用 Q 函数来找到最佳策略,因为 Q 函数告诉我们哪个动作是在某种状态下执行的最佳动作。 您认为我们不使用 Q 函数就能直接找到最优策略吗? 是。 我们可以。 在策略梯度方法中,我们无需使用 Q 函数就可以找到最优策略。
ApacheCN_飞龙
2023/04/23
6610
MADQN:多代理合作强化学习
处理单一任务是强化学习的基础,它的目标是在不确定的环境中采取最佳行动,产生相对于任务的最大长期回报。但是在多代理强化学习中,因为存在多个代理,所以代理之间的关系可以是合作的,也可以是对抗,或者两者的混合。多代理的强化学习引入了更多的复杂性,每个代理的状态不仅包括对自身的观察,还包括对其他代理位置及其活动的观察。
deephub
2024/03/20
3830
MADQN:多代理合作强化学习
写给开发同学的 AI 强化学习入门指南
作者:bear 该篇文章是我学习过程的一些归纳总结,希望对大家有所帮助。 最近因为 AI 大火,搞的我也对 AI 突然也很感兴趣,于是开启了 AI 的学习之旅。其实我也没学过机器学习,对 AI 基本上一窍不通,但是好在身处在这个信息爆炸的时代,去网上随便一搜发现大把的学习资料。 像这个链接里面:https://github.com/ty4z2008/Qix/blob/master/dl.md 就有很多资料,但是这相当于大海捞针。在学习之前我们先明确自己的目的是什么,如题这篇文章是入门强化学习,那么就需要定义
腾讯技术工程官方号
2023/04/29
1.6K0
写给开发同学的 AI 强化学习入门指南
【强化学习】Double DQN(Double Deep Q-Network)算法
强化学习中的深度Q网络(DQN)是一种将深度学习与Q学习结合的算法,它通过神经网络逼近Q函数以解决复杂的高维状态问题。然而,DQN存在过估计问题(Overestimation Bias),即在更新Q值时,由于同时使用同一个网络选择动作和计算目标Q值,可能导致Q值的估计偏高。
不去幼儿园
2025/01/08
2.1K0
【强化学习】Double DQN(Double Deep Q-Network)算法
深度学习算法(第37期)----如何用强化学习玩游戏?
上期我们一起学习了强化学习中的时间差分学习和近似Q学习的相关知识, 深度学习算法(第36期)----强化学习之时间差分学习与近似Q学习 今天我们一起用毕生所学来训练一个玩游戏的AI智能体。
智能算法
2019/12/04
1.1K0
机器学习——强化学习与深度强化学习
近年来,强化学习(Reinforcement Learning, RL)在多个领域取得了巨大的进展。从早期简单的迷宫导航问题到今天 AlphaGo 击败围棋世界冠军,强化学习的潜力得到了充分展现。而随着深度学习的引入,深度强化学习(Deep Reinforcement Learning, DRL)更是将这一技术推向了前所未有的高度。本篇文章将深入探讨强化学习与深度强化学习的基本原理、常见算法以及应用场景,旨在为读者提供一个详尽的学习路线图。
hope kc
2024/10/09
2.4K0
【强化学习】策略梯度(Policy Gradient,PG)算法
在强化学习中,Policy Gradient(策略梯度)算法是一类通过优化策略函数直接来求解最优策略的方法。与基于值函数(例如Q学习和SARSA)的方法不同,策略梯度方法直接对策略函数进行建模,目标是通过梯度下降的方法来最大化预期的累积奖励(即期望回报)。这些算法主要适用于连续的动作空间或高维问题,能够在复杂的环境中取得较好的性能。
不去幼儿园
2024/12/18
1K0
【强化学习】策略梯度(Policy Gradient,PG)算法
TensorFlow 强化学习:1~5
人工神经网络是一种计算系统,为我们提供了解决诸如图像识别到语音翻译等具有挑战性的机器学习任务的重要工具。 最近的突破,例如 Google DeepMind 的 AlphaGo 击败了最好的围棋玩家,或者卡内基梅隆大学的 Libratus 击败了世界上最好的职业扑克玩家,都证明了算法的进步。 这些算法像人类一样学习狭窄的智能,并达到超人水平的表现。 用通俗易懂的话说,人工神经网络是我们可以在计算机上编程的人脑的松散表示。 确切地说,这是受我们对人脑功能知识的启发而产生的一种方法。 神经网络的一个关键概念是创建输入数据的表示空间,然后在该空间中解决问题。 也就是说,从数据的当前状态开始扭曲数据,以便可以以不同的状态表示数据,从而可以解决有关的问题陈述(例如分类或回归)。 深度学习意味着多个隐藏的表示,即具有许多层的神经网络,可以创建更有效的数据表示。 每一层都会细化从上一层收到的信息。
ApacheCN_飞龙
2023/04/27
7030
【DRL】深度强化学习介绍
随着深度学习的迅猛发展,深度强化学习(Deep Reinforcement Learning, DRL)将深度学习与强化学习相结合,使得处理高维状态空间成为可能。
不去幼儿园
2024/12/03
2250
【DRL】深度强化学习介绍
详解深度强化学习展现TensorFlow 2.0新特性
自TensorFlow官方发布其2.0版本新性能以来,不少人可能对此会有些许困惑。因此博主Roman Ring写了一篇概述性的文章,通过实现深度强化学习算法来具体的展示了TensorFlow 2.0的特性。
刀刀老高
2019/05/15
6870
详解深度强化学习展现TensorFlow 2.0新特性
推荐阅读
相关推荐
【RL Base】强化学习核心算法:深度Q网络(DQN)算法
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验