大型新型网站,centos安装wordpress,装修设计软件 知乎,什么是c2c平台基本语法
React.memo 高阶组件的使用场景说明#xff1a;
React 组件更新机制#xff1a;只要父组件状态更新#xff0c;子组件就会无条件的一起更新。
子组件 props 变化时更新过程#xff1a;组件代码执行 - JSX Diff#xff08;配合虚拟 DOM#xff09;- 渲…基本语法
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 钩子函数来实现。
import { useState } from react
import ReactDOM from react-domconst Child2 ({ count }) {console.log(Child2 子组件代码执行了)return div style{{ backgroundColor: #abc }}子组件2{count}/div
}const Child1 () {console.log(Child1 子组件代码执行了)return div style{{ backgroundColor: #def }}子组件1/div
}const App () {const [count, setCount] useState(0)return (div style{{ backgroundColor: pink, padding: 10 }}h1计数器{count}/h1button onClick{() setCount(count 1)}1/buttonhr /{/* 子组件 */}Child1 /br /Child2 count{count} //div)
}export default App 语法
使用场景当你想要避免函数组件 props 没有变化而产生的不必要更新时就要用到 React.memo 了。
作用记忆组件上一次的渲染结果在 props 没有变化时复用该结果避免函数组件不必要的更新。 解释
React.memo 是一个高阶组件用来记忆memorize组件参数Child需要被记忆的组件或者说是需要避免不必要更新的组件。返回值MemoChildReact 记住的 Child 组件。 原理通过对比检查更新前后 props 是否相同来决定是否复用上一次的渲染结果
如果相同复用上一次的渲染结果如果不同重新渲染组件。 并不是所有的组件都适合使用memo比如child2组件每次都需要重新渲染使用memo反而会使性能变得更低逻辑也变得更复杂 基本用法
如果你的组件在相同 props 的情况下渲染相同的结果那么你可以通过将其包装在 React.memo 中调用以此通过记忆组件渲染结果的方式来提高组件的性能表现。这意味着在这种情况下React 将跳过渲染组件的操作并直接复用最近一次渲染的结果
React.memo 仅检查 props 变更。如果函数组件被 React.memo 包裹且其实现中拥有 useStateuseReducer 或 useContext 的 Hook当 state 或 context 发生变化时它仍会重新渲染。
默认情况下React.memo 只会对更新前后的 props 进行浅对比shallow compare与 PureComponent 相同。 也就是说对于对象类型的 prop 来说只会比较引用
如果更新前后的引用相同复用上一次的渲染结果不会重新渲染该组件。如果更新前后的引用不同重新渲染该组件。 默认情况下其只会对复杂对象做浅层对比如果你想要控制对比过程那么请将自定义的比较函数通过第二个参数传入来实现
如果你要手动控制比较过程可以使用 React.memo 的第二个参数 解释
第二个参数用来比较更新前后 props 的函数。返回值如果返回 true表示记住不重新渲染该组件如果返回 false表示重新渲染该组件。
子组件Callback.jsx
export default function Callback() {console.log(callback)return (divcallback/div)
} 父组件App.jsx
import Callback from ./components/Callback
import {useState} from react;export default function App() {const [age, setAge] useState(20);function changeAge() {setAge(age 1)}return (divage: {age}button onClick{changeAge}修改age/buttonCallback //div)
}
修改父组件的state值后函数子组件内部的代码运行了相对而言有点费性能
优化如下
使用React.memo包裹子组件缓存上一次的结果默认情况下其只会对复杂对象做浅层对比如果你想要控制对比过程那么请将自定义的比较函数通过第二个参数传入来实现。 子组件Callback.jsx
import React from react;function Callback() {console.log(callback)return (divcallback/div)
} export default React.memo(Callback)
优化后父组件的state数据变更后没有执行打印结果。
在父组件中定义个fn函数传入到子组件中
import Callback from ./components/Callback
import { useState} from react;export default function App() {console.log(app)const [age, setAge] useState(20);function changeAge() {setAge(age 1)}function fn() {}return (divage: {age}button onClick{changeAge}修改age/buttonCallback fn{fn} //div)
}
此时父组件的state数据改变后会引起子组件的内部代码运行。打印了结果相对而言性能有损耗。 优化如下
useCallback优化性能
将fn函数通过useCallback缓存起来
import Callback from ./components/Callback
import {useCallback, useState} from react;export default function App() {console.log(app)const [age, setAge] useState(20);function changeAge() {setAge(age 1)}let fn useCallback(() {}, [])return (divage: {age}button onClick{changeAge}修改age/buttonCallback fn{fn} //div)
}
此时修改父组件的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 的本质一样都是进行依赖控制。