React学习———React.memo、useMemo和useCallback

React.memo

React.memo是React提供的一个高阶组件,用于优化函数组件的性能,它通过记忆组件的渲染结果,避免在父组件重新渲染时,子组件不必要的重新渲染
React.memo会对组件的props进行浅比较,如果props没有变化,则组件不会重新渲染

基本用法

import React from 'react'
const MyComponent = (props) => {
	console.log('组件渲染了')
	return <div>{props.value}</div>
}
export default React.memo(MyComponent)

工作原理

  • 默认浅比较:React.memo会对传递给组件的props进行浅比较,如果props没有变化,则跳过重新渲染
  • 自定义比较函数(可选):如果需要更复杂的比较逻辑,可以通过第二个参数传入自定义比较函数

自定义比较函数

const MyComponent = (props) => {
	console.log('组件渲染了')
	return <div>{props.value}</div>
}
const areEqual = (prevProps, nextProps) => {
	// 自定义比较逻辑
	return prevProps.value === nextProps.value
}
export default React.memo(MyComponent, areEqual)

使用场景

  • 纯函数组件:当组件的渲染结果完全依赖于props,且没有内部状态或副作用时,使用React.memo可以有效避免不必要的渲染
  • 频繁渲染的组件:在父组件频繁更新,但子组件的props变化较少的情况下,使用React.memo可以显著提升性能
  • 大型列表或复杂组件:对于渲染成本较高的组件,使用React.memo可以减少渲染次数,提升应用的整体性能

注意事项

  • 浅比较的局限性:React.memo默认使用浅比较。如果props是复杂的嵌套对象或数组,可能需要自定义比较函数
  • 状态或上下文变化:React.memo只对props的变化敏感,如果组件依赖于状态(state)或上下文(context),这些变化仍会触发重新渲染
  • 过度优化:不要滥用React.memo。因为浅比较和自定义比较函数本身也会带来一定的性能开销

useMemo

useMemo是一个React Hook,用于缓存计算结果,避免在每次渲染时重复执行耗时的计算

特点

  • 用于性能优化,减少不必要的计算
  • 只有依赖项发生变化时,才会重新计算值
  • 返回缓存的计算结果

基本用法

import React, { useMemo, useState } from 'react';
function ExpensiveCalculation(num){
	console.log('Calculating...');
	return num * 2
}
function App(){
	const [count,setCount] = useState(0)
	const [other, setOther] = useState(0);
	const result = useMemo(() => ExpensiveCalculation(count), [count])
	return (
    <div>
      <p>Result: {result}</p>
      <button onClick={() => setCount(count + 1)}>Increment Count</button>
      <button onClick={() => setOther(other + 1)}>Increment Other</button>
    </div>
  );
}
export default App
  • 第一个参数:回调函数
  • 第二个参数(依赖数组):当依赖项发生变化时,useMemo会重新执行回调函数并返回新的计算结果,如果依赖项没有变化,useMemo会直接返回之前缓存的结果,而不是重新执行回调函数

注意事项

  • useMemo只会缓存计算结果,不会缓存函数本身,如果需要缓存函数本身,使用useCallback
  • 如果依赖项数组为空([]),useMemo的值只会在组件首次渲染时计算一次

useCallback

useCallback是React提供的一个Hook,用于换成函数的引用,避免在组件重新渲染时不必要的重新创建函数

基本用法

const memozedCallback = useCallback(
	() => {
		// 函数逻辑
	},
	[依赖项]
)
  • 第一个参数:需要缓存的函数
  • 第二个参数(依赖数组):当依赖项发生变化时,useCallback会返回一个新的函数引用;如果依赖项没有变化,则返回缓存的函数引用

为什么需要useCallback

  • 在React中,函数组件每次渲染都会重新创建内部的函数,如果这些函数被传递给子组件或用作依赖项,可能会导致性能问题或不必要的副作用,
  • 例如:子组件的不必要重新渲染;性能浪费,尤其在函数被频繁创建时

使用场景

  • 避免子组件不必要的重新渲染
import React, { useState, useCallback, useEffect } from 'react';
// ({onClick}):表示从props中解构出onClick的属性
// ({onClick:() => void}):为onClick属性添加类型注解,表示他是一个函数,且没有参数,返回值为void
const Child = React.memo(({onClick}:{onClick:() => void})=>{
	console.log('子组件渲染')
	return <button onClick={onClick}>点击</button>
})

function Parent(){
	const [count,setCount] = useState(0)
	
	const handleClick = useCallback(() => {
		console.log('按钮点击')
	}, [])

	return (
		<div>
			<p>计数:{count}</p>
			<button onClick={() => setCount(count+1)}>增加计数</button>
			<Child onClick={handleClick} />
		</div>
	)
}

1:未使用useCallback时,每次Parent组件重新渲染时,handleClick都会被重新创建,导致Child组件也会重新渲染
2:使用useCallback后:handleClick的引用不会改变,Child组件不会重新渲染

  • 作为依赖项传递给useEffect
import React, { useState, useCallback, useEffect } from 'react';
function Example(){
	const [count,setCount] = useState(0)
	const logCount = useCallback(() => {
		console.log(`当前计数:${count}`);
	}, [count])
	useEffect(() => {
		logCount()
	}, [logCount]) // 使用 useCallback 缓存的函数作为依赖项
	return <button onClick={() => setCount(count + 1)}>增加计数</button>;
}

1:未使用useCallback时:logCount 每次渲染都会重新创建,导致useEffect每次都重新执行
2:使用useCallback后:logCount只有在count 变化时才会更新,减少不必要的副作用

useCallback和React.memo的区别

特性useCallbackReact.memo
作用对象用于优化函数用于优化组件
核心功能避免函数在组件重新渲染时被重新创建避免组件因props未变化而重新渲染
工作原理缓存函数引用,只有依赖项变化时才重新创建浅比较props,决定是否跳过组件渲染
适用场景当函数被传递给子组件或用作依赖项时当组件的props很少变化时
性能优化的目标减少函数的重新创建次数减少组件的重新渲染次数

useCallback和React.memo结合使用

在实际开发中,经常会被结合使用,尤其是在父组件向子组件传递函数时

useMemo和React.memo的区别

特性useMemoReact.memo
作用缓存计算结果优化组件渲染,避免不必要的重新渲染
触发条件比较依赖项是否变化比较组件的props是否变化
适用场景用于函数或计算逻辑的性能优化用于组件级别的性能优化
返回值返回缓存的计算结果返回优化后的组件

总结

  • React.memo用于组件级别的性能优化,避免子组件不必要的重新渲染
  • useMemo用于缓存计算结果,适合优化耗时的计算逻辑
  • useCallback用于缓存函数引用,避免优化子组件接收函数props的场景
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值