useMemo、useCallback 与自定义 Hook
性能优化直觉、抽取复用逻辑。
useMemo、useCallback 与自定义 Hook
这一课你将能做到
- 说出
useMemo/useCallback是「按需优化」,不是默认必写 - 写出一个最小自定义 Hook(如
useToggle) - 知道自定义 Hook 必须以
use开头的约定
为什么要学
你会在网上看到满屏 useMemo。
入门时更重要的是:先写对,再量是否卡,再优化。
自定义 Hook 则是把「有状态的逻辑」复用出去——开关、倒计时、窗口宽度——这比过早 memo 更值得学。
人话:Hook 就是「能调用其他 Hook 的函数」;你自己写的也算,只要名字以 use 开头。
本站多处开关、抽屉,逻辑相似。复制三份 useState 不如一个 useToggle。
先建立图像
useMemo(() => 计算结果, [依赖]) → 记住某个「值」
useCallback(() => 函数, [依赖]) → 记住同一个「函数引用」
useXxx(...) → 你自己的 Hooks 组合
React 编译器等工具在变强:官方也不再鼓励到处手写 memo。入门把自定义 Hook 写对,比背优化口诀重要。
跟着做
步骤 1:自定义 Hook useToggle(完整可抄)
import { useState, useCallback } from "react";
export function useToggle(initial = false) {
const [on, setOn] = useState(initial);
const toggle = useCallback(() => setOn((v) => !v), []);
const setTrue = useCallback(() => setOn(true), []);
const setFalse = useCallback(() => setOn(false), []);
return { on, toggle, setTrue, setFalse };
}
export function Panel() {
const { on, toggle } = useToggle();
return (
<button type="button" onClick={toggle}>
{on ? "开" : "关"}
</button>
);
}
把开关逻辑挪出组件,路径页、设置页都能用。
useCallback 在这里只是让返回的函数引用稳定;没有 React.memo 的子组件时,收益很小,但展示「Hook 里也能用别的 Hook」。
步骤 2:useMemo 示例(理解即可)
import { useMemo, useState } from "react";
export function VisibleList({ items }) {
const [showDone, setShowDone] = useState(true);
const visible = useMemo(() => {
return items.filter((x) => (showDone ? true : !x.done));
}, [items, showDone]);
return (
<>
<button type="button" onClick={() => setShowDone((v) => !v)}>
切换
</button>
<ul>
{visible.map((x) => (
<li key={x.id}>{x.title}</li>
))}
</ul>
</>
);
}
若 filter 很轻、列表很小,直接在渲染里算完全可以。列表极大、计算明显卡顿再 memo。