React Hooks 入门:常用 API 与使用注意
React Hooks 入门:常用 API 与使用注意
Hooks 让你在函数组件里使用 state、副作用、上下文等能力,而无需写 class。React 16.8 起稳定支持。使用 Hooks 时需遵守 Hooks 规则(只在顶层调用、只在 React 函数里调用)。
基础 Hooks
useState
为组件增加本地状态。
import { useState } from "react";
function Counter() {
const [count, setCount] = useState(0);
return (
<button type="button" onClick={() => setCount((c) => c + 1)}>
{count}
</button>
);
}
- 初始值可以是任意类型;若初始状态计算较贵,可传入
useState(() => expensive())(惰性初始化)。 - 不要直接修改 state 对象/数组,应拷贝后再
setState。
useEffect
处理副作用:请求数据、订阅、操作 DOM、定时器等。
import { useEffect, useState } from "react";
function Profile({ userId }) {
const [data, setData] = useState(null);
useEffect(() => {
let cancelled = false;
async function load() {
const res = await fetch(`/api/user/${userId}`);
const json = await res.json();
if (!cancelled) setData(json);
}
load();
return () => {
cancelled = true;
};
}, [userId]);
return data ? <p>{data.name}</p> : <p>加载中…</p>;
}
- 依赖数组:
[]表示仅挂载/卸载时执行一次;[userId]在userId变化时重新执行。 - 清理函数
return () => {}:取消订阅、清除定时器、忽略过期请求结果等。
useContext
消费 React.createContext 提供的值,避免层层传递 props。
const ThemeContext = React.createContext("light");
function Button() {
const theme = useContext(ThemeContext);
return <button className={theme}>OK</button>;
}
额外 Hooks(常用)
useReducer
适合状态逻辑复杂、多子值或依赖上一状态更新的场景,可视为 useState 的强化版。
const [state, dispatch] = useReducer(reducer, initialState);
useMemo
缓存计算结果,依赖不变则复用上次值,减轻子组件重复计算(注意:不是万能性能药)。
const sorted = useMemo(() => items.slice().sort(compare), [items]);
useCallback
缓存函数引用,常与子组件 React.memo 配合,避免无关重渲染。
const onSave = useCallback(() => {
save(id);
}, [id]);
useRef
保存可变引用且不触发重渲染:DOM 节点、定时器 id、任意可变盒。
const inputRef = useRef(null);
useEffect(() => {
inputRef.current?.focus();
}, []);
useLayoutEffect
在浏览器绘制之后、用户看到之前同步执行,适合测量 DOM、避免闪烁;大部分场景用 useEffect 即可。
自定义 Hook
把可复用的状态逻辑抽成 useXxx 函数,内部可调用其他 Hooks。
function useWindowWidth() {
const [w, setW] = useState(() => window.innerWidth);
useEffect(() => {
const onResize = () => setW(window.innerWidth);
window.addEventListener("resize", onResize);
return () => window.removeEventListener("resize", onResize);
}, []);
return w;
}
Hooks 使用规则(摘要)
- 只在函数组件顶层或自定义 Hook 里调用 Hooks,不要在循环、条件或嵌套函数里调用。
- 自定义 Hook 以
use开头,便于 ESLint 插件eslint-plugin-react-hooks检查。
小结
| Hook | 典型用途 |
|---|---|
useState | 组件内状态 |
useEffect | 副作用与清理 |
useContext | 跨层数据 |
useReducer | 复杂状态转移 |
useMemo / useCallback | 按需稳定引用、减少无效计算 |
useRef | DOM 与可变值 |
新代码建议以函数组件 + Hooks为主;类组件仍可在维护旧项目时遇到。官方文档:React Hooks 概览。
