您现在的位置是:亿华云 > 热点

React Hook 四种组件优化

亿华云2025-10-04 03:31:00【热点】5人已围观

简介React Hook 已成为当前最流行的开发范式,React 16.8 以后基于 Hook 开发极大简化开发者效率,同时不正确的使用 React Hook也带来了很多的性能问题,本文梳理基于 Reac

React Hook 已成为当前最流行的种组件开发范式,React 16.8 以后基于 Hook 开发极大简化开发者效率,优化同时不正确的种组件使用 React Hook也带来了很多的性能问题,本文梳理基于 React Hook 开发组件的优化过程中如何提高性能。

组件抽取

优化前

每次点击 Increase​ 都会引起子组件 Child 的种组件渲染,哪怕子组件并没有状态变化:

function Before(){

console.log(Demo1 Parent)

let [count,优化setCount] = useState(0)

let [name,setName] = useState(-)

const handleClick = ()=>{

setCount(count+1)

}

const handleInput = (e)=>{

setName(e.target.value)

}

return (

{ count}

)

}

// 子组件

function Child(props){

console.log(Demo1 Child)

return (

子组件渲染:{ props.name}

)

}

优化后

只需要把 Increase 抽取成独立的组件即可。此时点击按钮,种组件子组件并不会渲染。优化

/

**

* 优化后,种组件Increase提取以后,优化上下文发生变化,种组件组件内

* @returns

*/

function Increase(){

console.log(Child Increase)

let [count,优化setCount] = useState(0)

const handleClick = ()=>{

setCount(count+1)

}

return (

{ count}

)

}

function After(){

console.log(Demo1 Parent)

let [name,setName] = useState(-)

const handleInput = (e)=>{

setName(e.target.value)

}

return (

)

}

// 子组件

function Child(props){

console.log(Demo1 Child)

return (

子组件渲染:{ props.name}

)

}

memo 优化组件

同样基于上述优化前代码,即使不抽取组件,种组件使用 memo 优化后,优化当点击按钮时,种组件也不会触发二次渲染。

// 优化前

function AfterMemo(){

console.log(Demo1 Parent)

let [count,setCount] = useState(0)

let [name,setName] = useState(-)

const handleClick = ()=>{

setCount(count+1)

}

const handleInput = (e)=>{

setName(e.target.value)

}

return (

{ count}

)

}

// 子组件

const Child = memo((props)=>{

console.log(Demo1 Child)

return (

子组件渲染:{ props.name}

)

})

React.memo 语法

React.memo 为高阶组件,与 React.PureComponent相似。

function TestComponent(props){

// 使用 props 渲染

}

function areEqual(prevProps,nextProps){

/

*

如果把 nextProps 传入 render 方法的返回结果与

将 prevProps 传入 render 方法的返回结果一致则返回 true,

否则返回 false

*/

}

export default React.memo(TestComponent,areEqual)

与 class 组件中 shouldComponentUpdate() 方法不同的是,如果 props 相等,areEqual 会返回 true;如果 props 不相等,则返回 false。这与 shouldComponentUpdate 方法的源码下载返回值相反。

useCallback 优化组件

如果已经用了 memo​ ,当遇到下面这种场景时,同样会触发子组件渲染。比如,给 Child​ 绑定一个 handleClick​ ,子组件内部增加一个按钮,当点击子组件的按钮时,更改 count​ 值,即使没有发生 name​ 变化,也同样会触发子组件渲染,为什么?memo​ 不是会判断  name 变化了,才会更新吗?

function Before(){

console.log(Demo1 Parent)

let [count,setCount] = useState(0)

let [name,setName] = useState(-)

const handleClick = ()=>{

setCount(count+1)

}

const handleInput = (e)=>{

setName(e.target.value)

}

const handleChange = ()=>{

setCount(count+1)

}

return (

{ count}

)

}

// 子组件

const Child = memo((props)=>{

console.log(Demo1 Child)

return (

子组件渲染:{ props.name}

)

})

并不是  memo​ 没有生效,是因为当状态发生变化时,父组件会重新执行,导致重新创建了新的handleChange​ 函数,而 handleChange 的变化导致了子组件的再次渲染。

优化后

点击父组件的Increase​按钮,更改了 count​ 值,经过 useCallback​ 包裹 handleChange​ 函数以后,我们会发现子组件不再渲染,说明每当父组件执行的时候,并没有创建新的 handleChange​ 函数,云服务器这就是通过 useCallback​ 优化后的效果。即使我们点击子组件的按钮,也同样不会触发子组件的渲染,同样 count 会进行累加。

function After(){

console.log(Demo1 Parent)

let [count,setCount] = useState(0)

let text = useRef();

let [name,setName] = useState(-)

const handleClick = ()=>{

setCount(count+1)

}

const handleInput = (e)=>{

setName(e.target.value)

}

const handleChange = useCallback(()=>{

// 为了让 count 能够累加,我们使用ref 获取值

let val = parseInt(text.current.textContent);

setCount(val+1)

},[])

return (

{ count}

)

}

useCallback 作用

// 用法

useCallback(()=>{

// to-do

},[])

// 示例

function App(){

// 点击按钮调用此函数,但返回被缓存

const onClick = useCallback(() => {

console.log(我被缓存了,怎么点击都返回一样);

}, []);

return (

);

}useCallback 接收 2 个参数,第一个为缓存的函数,第二个为依赖值主要用于缓存函数,第二次会返回同样的结果。

useMemo 优化

我们定义了一个total​函数,内部使用 1 填充了100次,通过 reduce​ 计算总和,经过测试发现点击 Increase​按钮后,只会执行 total1​ ,不会执行 total2​,假设total​计算量巨大,就会造成内存的浪费,通过 useMemo 可以帮我们缓存计算值。

function Before(){

console.log(Demo1 Parent)

let [count,setCount] = useState(0)

const handleClick = ()=>{

setCount(count+1)

}

const total1 = ()=>{

console.log(计算求和1)

let arr = Array.from({ length:100 }).fill(1)

return arr.reduce((prev,next)=>prev+next,0)

}

// 缓存对象值

const total2 = useMemo(()=>{

console.log(计算求和2)

let arr = Array.from({ length:100 }).fill(1)

return arr.reduce((prev,next)=>prev+next,0)

},[count])

return (

{ count}

{ total1()}

{ total2}

)

}

useMemo 语法

const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);

传入一个函数进去,会返回一个memoized 值,需要注意的是,函数内必须有返回值

第二个参数会依赖值,服务器托管当依赖值更新时,会重新计算。

useCallback 和 useMemo 区别

他们都用于缓存,useCallback​ 主要用于缓存函数,返回一个 缓存后 函数,而 useMemo 主要用于缓存值,返回一个缓存后的值。

以上就是本次给大家整理的集中常见的组件优化,当然合理使用useEffect useLayout希望对不了解的朋友有用。

很赞哦!(9894)