Hooks 避坑指南:5 个常见错误及解决方案
错误 1:在条件语句中使用 Hooks
❌ 错误写法:
function UserProfile({ showEmail }) {
const [name, setName] = useState('');
if (showEmail) {
const [email, setEmail] = useState(''); // 错误!
}
return <div>{name}</div>;
}
✅ 正确写法:
function UserProfile({ showEmail }) {
const [name, setName] = useState('');
const [email, setEmail] = useState(''); // 始终定义
return <div>{name}{showEmail && email}</div>;
}
原因: Hooks 必须在顶层调用,条件执行会破坏调用顺序。
错误 2:useEffect 依赖项缺失
❌ 错误写法:
function Counter() {
const [count, setCount] = useState(0);
useEffect(() => {
const timer = setInterval(() => {
setCount(count + 1); // 始终是旧值!
}, 1000);
return () => clearInterval(timer);
}, []); // 缺少 count 依赖
return <div>{count}</div>;
}
✅ 正确写法:
function Counter() {
const [count, setCount] = useState(0);
useEffect(() => {
const timer = setInterval(() => {
setCount(prev => prev + 1); // 使用函数式更新
}, 1000);
return () => clearInterval(timer);
}, []);
return <div>{count}</div>;
}
技巧: 使用函数式更新 setState(prev => ...) 可避免依赖问题。
错误 3:useEffect 中直接修改状态
❌ 错误写法:
function TodoList() {
const [todos, setTodos] = useState([]);
useEffect(() => {
const newTodo = { id: 1, text: 'Learn Hooks' };
todos.push(newTodo); // 直接修改!
setTodos(todos);
}, []);
return <div>{todos.length}</div>;
}
✅ 正确写法:
function TodoList() {
const [todos, setTodos] = useState([]);
useEffect(() => {
setTodos(prev => [...prev, { id: 1, text: 'Learn Hooks' }]);
}, []);
return <div>{todos.length}</div>;
}
原因: React 依赖不可变性检测变化,直接修改不会触发重渲染。
错误 4:useCallback/useMemo 滥用
❌ 错误写法:
function Form({ onSubmit }) {
const [value, setValue] = useState('');
// 不必要的记忆化
const handleChange = useCallback((e) => {
setValue(e.target.value);
}, []);
const doubled = useMemo(() => value * 2, [value]);
return <input onChange={handleChange} />;
}
✅ 正确写法:
function Form({ onSubmit }) {
const [value, setValue] = useState('');
// 简单场景直接定义
const handleChange = (e) => setValue(e.target.value);
return <input onChange={handleChange} />;
}
技巧: 仅在传递回调给子组件或计算开销大时使用记忆化。
错误 5:自定义 Hooks 命名不规范
❌ 错误写法:
function useUserData() { // 不是真正的 Hook
const userData = fetchUser();
return userData;
}
function fetchData() { // 应该是 Hook
const [data, setData] = useState(null);
return data;
}
✅ 正确写法:
function fetchUserData() { // 普通函数
return fetchUser();
}
function useUserData() { // 自定义 Hook
const [data, setData] = useState(null);
return data;
}
规则: 使用 Hooks 的函数必须以 use 开头。
📌 核心要点总结
- 顶层调用 — 永远不要在条件、循环或嵌套函数中调用 Hooks
- 完整依赖 — useEffect/useMemo/useCallback 的依赖数组要完整
- 不可变更新 — 始终创建新对象/数组,不要直接修改
- 适度优化 — 不要过早使用 useCallback/useMemo
- 命名规范 — 自定义 Hooks 必须以
use开头