react hooks--React.memo

打印 上一主题 下一主题

主题 991|帖子 991|积分 2973

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x
基本语法

React.memo 高阶组件的使用场景阐明:
React 组件更新机制:只要父组件状态更新,子组件就会无条件的一起更新。


  • 子组件 props 变化时更新过程:组件代码实行 -> JSX Diff(共同假造 DOM)-> 渲染(变化后的内容)【 DOM 操作】。
  • 子组件 props 无变化更新过程:组件代码实行 -> JSX Diff(共同假造 DOM)【无 DOM 操作】。
注意:此处更新指的是组件代码实行、JSX 举行 Diff 操作(纯 JS 的操作,速率非常快,不会对性能产生太多影响)。


  • 假如组件 props 改变了,那么,该组件就必须要更新,才气接收到最新的 props。
  • 但是,假如组件 props 没有改变时,组件也要举行一次更新。实际上,这一次更新是没有须要的。
假如要避免组件 props 没有变化而举行的不须要更新(Diff),这种情况下,就要使用 React.memo 高阶组件。
注:对于 class 组件来说,可以使用 PureComponent 或 shouldComponentUpdate 钩子函数来实现。
  1. import { useState } from 'react'
  2. import ReactDOM from 'react-dom'
  3. const Child2 = ({ count }) => {
  4.   console.log('Child2 子组件代码执行了')
  5.   return <div style={{ backgroundColor: '#abc' }}>子组件2:{count}</div>
  6. }
  7. const Child1 = () => {
  8.   console.log('Child1 子组件代码执行了')
  9.   return <div style={{ backgroundColor: '#def' }}>子组件1</div>
  10. }
  11. const App = () => {
  12.   const [count, setCount] = useState(0)
  13.   return (
  14.     <div style={{ backgroundColor: 'pink', padding: 10 }}>
  15.       <h1>计数器:{count}</h1>
  16.       <button onClick={() => setCount(count + 1)}>+1</button>
  17.       <hr />
  18.       {/* 子组件 */}
  19.       <Child1 />
  20.       <br />
  21.       <Child2 count={count} />
  22.     </div>
  23.   )
  24. }
  25. export default App
复制代码

语法:
使用场景:当你想要避免函数组件 props 没有变化而产生的不须要更新时,就要用到 React.memo 了。
作用:影象组件上一次的渲染结果,在 props 没有变化时复用该结果,避免函数组件不须要的更新


表明:


  • React.memo 是一个高阶组件,用来影象(memorize)组件
  • 参数(Child):需要被影象的组件,大概说是需要避免不须要更新的组件。
  • 返回值(MemoChild):React 记着的 Child 组件。

原理:通过对比检查更新前后 props 是否雷同,来决定是否复用上一次的渲染结果


  • 假如雷同,复用上一次的渲染结果;
  • 假如不同,重新渲染组件。

并不是所有的组件都适合使用memo,比如child2组件,每次都需要重新渲染,使用memo反而会使性能变得更低,逻辑也变得更复杂

基本用法

假如你的组件在雷同 props 的情况下渲染雷同的结果,那么你可以通过将其包装在 React.memo 中调用,以此通过影象组件渲染结果的方式来进步组件的性能表现。这意味着在这种情况下,React 将跳过渲染组件的操作并直接复用最近一次渲染的结果
React.memo 仅检查 props 变更。假如函数组件被 React.memo 包裹,且其实现中拥有 useStateuseReduceruseContext 的 Hook,当 state 或 context 发生变化时,它仍会重新渲染。
默认情况下,React.memo 只会对更新前后的 props 举行浅对比(shallow compare)与 PureComponent 雷同。

也就是说,对于对象范例的 prop 来说,只会比力引用


  • 假如更新前后的引用雷同,复用上一次的渲染结果(不会重新渲染该组件)。
  • 假如更新前后的引用不同,重新渲染该组件。

默认情况下其只会对复杂对象做浅层对比,假如你想要控制对比过程,那么请将自定义的比力函数通过第二个参数传入来实现
假如你要手动控制比力过程,可以使用 React.memo 的第二个参数:


表明:


  • 第二个参数:用来比力更新前后 props 的函数。
  • 返回值:假如返回 true,表现记着(不重新渲染)该组件;假如返回 false,表现重新渲染该组件。
子组件Callback.jsx
  1. export default function Callback() {
  2.     console.log('callback')
  3.     return (
  4.         <div>callback</div>
  5.     )
  6. }
复制代码

父组件App.jsx:
  1. import Callback from './components/Callback'
  2. import {useState} from "react";
  3. export default function App() {
  4.     const [age, setAge] = useState(20);
  5.     function changeAge() {
  6.         setAge(age + 1)
  7.     }
  8.   return (
  9.       <div>
  10.           age: {age}
  11.           <button onClick={changeAge}>修改age</button>
  12.           <Callback />
  13.       </div>
  14.   )
  15. }
复制代码
修改父组件的state值后,函数子组件内部的代码运行了,相对而言有点费性能
优化如下:
使用React.memo包裹子组件,缓存上一次的结果,默认情况下其只会对复杂对象做浅层对比,假如你想要控制对比过程,那么请将自定义的比力函数通过第二个参数传入来实现。

子组件Callback.jsx
  1. import React from 'react';
  2. function Callback() {
  3.     console.log('callback')
  4.     return (
  5.         <div>callback</div>
  6.     )
  7. }
  8. ++ export default React.memo(Callback)
复制代码
优化后,父组件的state数据变更后,没有实行打印结果。
在父组件中定义个fn函数传入到子组件中:
  1. import Callback from './components/Callback'
  2. import { useState} from "react";
  3. export default function App() {
  4.     console.log('app')
  5.     const [age, setAge] = useState(20);
  6.     function changeAge() {
  7.         setAge(age + 1)
  8.     }
  9.     function fn() {
  10.         
  11.     }
  12.   return (
  13.       <div>
  14.           age: {age}
  15.           <button onClick={changeAge}>修改age</button>
  16.           <Callback fn={fn} />
  17.       </div>
  18.   )
  19. }
复制代码
此时,父组件的state数据改变后,会引起子组件的内部代码运行。打印告终果,相对而言性能有斲丧。

优化如下:
useCallback优化性能
fn函数通过useCallback缓存起来
  1. import Callback from './components/Callback'
  2. import {useCallback, useState} from "react";
  3. export default function App() {
  4.     console.log('app')
  5.     const [age, setAge] = useState(20);
  6.     function changeAge() {
  7.         setAge(age + 1)
  8.     }
  9.    
  10.     let fn = useCallback(() => {}, [])
  11.   return (
  12.       <div>
  13.           age: {age}
  14.           <button onClick={changeAge}>修改age</button>
  15.           <Callback fn={fn} />
  16.       </div>
  17.   )
  18. }
复制代码
此时修改父组件的state数据没有引起子组件的内部代码运行
因为fn函数被缓存了,地址没有发生改变,React.memo就认为props数据没有发生改变,所以没有表要重新运行函数。

useCallback怎样做的性能优化?


  • 在函数组件中,定义的一般的普通函数在每次组件更新渲染时都会重新生成一个函数,此时函数地址发生改变了,就会引起子组件内部代码运行,斲丧性能。
  • 优化:使用useCallback将函数缓存,每次组件更新渲染时,这个函数地址没有发生改变,所以传入到子组件的props数据没有发生发生改变,所以子组件内部代码没有重新实行。
  • React.memo是数据的浅对比,也就是地址的对比,只要传入参数地址发生改变就会重新实行子组件的代码。

总结

useMemo 用于缓存一些耗时的计算结果(返回值),只有当依赖项改变时才重新举行计算。 useCallback(func, [deps]) 等同于 useMemo(() => func, [deps]) useCallback 缓存的是方法的引用,useMemo 缓存的是方法的返回值,实用场景都是避免不须要的子组件渲染。 在类组件中有 React.PureComponent,与之对应的函数组件可以使用 React.memo,它们都会在自身 re-render 时,对每一个 props 项举行浅对比,假如引用没有发生改变,就不会触发渲染。 那么,useMemo 和 React.memo 有什么共同点呢?前者可以在组件内部使用,可以拥有比后者更细粒度的依赖控制。它们两个与 useCallback 的本质一样,都是举行依赖控制。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

悠扬随风

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表