react使用useMemo对性能的优化
尤大在知乎看见对react Hooks的评价:
其实 React 所谓的性能问题,大部分就是因为在设计层面上把大量的优化责任抛给了开发者,而且这些优化责任是琐碎的,没法通过一个简单的方案去一杆子搞定。由于绝大部分开发者是懒惰的(倾向于用最少的努力做出可以用的结果),这也就导致绝大部分 React 应用的性能并不理想(这里的 “不理想” 指的是没有达到优化的理论上限,不一定是那种用户能感知到的不理想)
使用useMemo性能优化
useMemo主要用来解决使用React hooks产生的无用渲染的性能问题。使用function的形式来声明组件,失去了shouldCompnentUpdate(在组件更新之前)这个生命周期,也就是说我们没有办法通过组件更新前条件来决定组件是否更新。而且在函数组件中,也不再区分mount和update两个状态,这意味着函数组件的每一次调用都会执行内部的所有逻辑,就带来了非常大的性能损耗。
- 来看看这个案例上性能的缺陷
index.js
jsx
import React,{ useState } from 'react';
import ReactDOM from 'react-dom';
function Example() {
const [state1, setState1] = useState(new Date().getTime())
const [state2, setState2] = useState(new Date().getTime())
return (
<>
<button onClick={() => { setState1(new Date().getTime()) }}>设置state1</button>
<button onClick={() => { setState2(new Date().getTime() + ',state2') }}>设置state2</button>
<ChildComponent name={state1}>{state2}</ChildComponent>
</>
)
}
function ChildComponent({ name, children }) {
function returnnames(name) {
console.log("子组件开始render")
return name + ',render'
}
const names = returnnames(name)
return (
<>
<div>{names}</div>
<div>{children}</div>
</>
)
}
ReactDOM.render(<Example />, document.querySelector("#root"))
这时候你会发现在浏览器中点击设置state2按钮
,ChildComponent的returnnames
方法都会执行,结果虽然没变,但是每次都执行,这就是性能的损耗。目前只有子组件,业务逻辑也非常简单,如果是做了业务上的请求,这将产生严重的后果。所以这个问题必须解决。当我们点击设置state2按钮
时,ChildComponent的returnnames
方法不能执行,只有在点击设置state2按钮
时才能执行。
如何解决?
jsx
import React, { useState, useMemo } from "react"
import ReactDOM from 'react-dom';
function Example() {
const [state1, setState1] = useState(new Date().getTime())
const [state2, setState2] = useState(new Date().getTime())
return (
<>
<button onClick={() => { setState1(new Date().getTime()) }}>设置state1</button>
<button onClick={() => { setState2(new Date().getTime() + ',state2') }}>设置state2</button>
<ChildComponent name={state1}>{state2}</ChildComponent>
</>
)
}
function ChildComponent({ name, children }) {
function returnnames(name) {
console.log("子组件开始render")
return name + ',render'
}
const names = useMemo(() => returnnames(name), [name])
return (
<>
<div>{names}</div>
<div>{children}</div>
</>
)
}
ReactDOM.render(<Example />, document.querySelector("#root"))
这时在浏览器中点击一下设置state2按钮
,ChildComponent的returnnames
就不再执行了。也节省了性能的消耗。