react项目性能优化的hook
前言:
在项目中开发中,性能优化是很重要的,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;
...