前言:
? ? ? ? 在項目中開發中,性能優化是很重要的,react有提供專門的hook,
useMemo
?和useCallback
?這里說一說他們。
區別:
特性 | useMemo | useCallback |
---|---|---|
返回值 | 緩存一個?值(計算結果) | 緩存一個?函數 |
依賴變化時 | 重新計算值 | 重新創建函數 |
典型用途 | 避免昂貴計算重復執行 | 避免子組件因函數引用變化重渲染 |
語法 | useMemo(() => value, deps) | useCallback(() => fn, deps) |
useMemo
?的適用場景
昂貴計算緩存
當組件中有需要復雜計算的值(如過濾列表、數學運算等),可以用?useMemo
?避免每次渲染重復計算。jsx
const filteredList = useMemo(() => {return largeList.filter(item => item.price > 100); }, [largeList]);
避免不必要的對象/數組重新創建
如果傳遞給子組件的 props 是對象或數組,且依賴項未變化時,用?useMemo
?緩存它們。jsx
const config = useMemo(() => ({ color: 'red', size: 10 }), []); return <ChildComponent config={config} />;
useCallback
?的適用場景
防止子組件無效重渲染
當父組件傳遞一個函數給子組件(尤其是?React.memo
?優化的子組件)時,用?useCallback
?緩存函數,避免因父組件重渲染導致函數引用變化,觸發子組件更新。jsx
const handleClick = useCallback(() => {console.log('Clicked!'); }, []);return <MemoizedChild onClick={handleClick} />;
總結:
useMemo
?→ 緩存?值(計算結果、對象/數組)。
useCallback
?→ 緩存?函數(避免子組件重渲染、穩定依賴項)。簡結:
需要緩存函數?用?
useCallback
。需要緩存其他值?用?
useMemo
。
實際項目使用場景:
1、封裝redux的user.ts中
import { UserInfo } from "@/types";
import { useCallback } from "react";
import { useDispatch, useSelector } from "react-redux";
import { setUserInfoAction, clearUser } from "../action";
import { getStateUser } from "../getter";export const useStateUserInfo = () => useSelector(getStateUser)export function useDispatchUser() {const dispatch = useDispatch()const stateSetUser = useCallback((info: UserInfo) => dispatch(setUserInfoAction(info)), [dispatch])const stateClearUser = useCallback(() => dispatch(clearUser()), [dispatch])return { stateSetUser, stateClearUser }
}
2、封裝路由跳轉的地方,router.tsx
import { useEffect, useMemo, useState } from "react";
import { Routes, Route } from "react-router-dom";....const routerBody = useMemo(() => {// 監聽 本地路由列表 同時存在長度大于1時 渲染路由組件if (mergeRouterList.length) {const data = mergeRouterList.map((item) => {let { [MENU_KEY]: key, [MENU_PATH]: path } = item;return (<Routekey={key}path={path.replace("/", "")}element={<Intercept{...item}menuList={ajaxUserMenuList}pageKey={key}/>}/>);});return <Routes>{data}</Routes>}return null}, [ajaxUserMenuList, mergeRouterList])return routerBody;
...