React Hooks 的优势和使用场景
1. Hooks 的核心优势
-
简化组件逻辑
- 将相关逻辑集中处理,告别生命周期方法的分散
- 示例:将数据获取和事件监听放在同一个
useEffect中
-
代码复用性提升
- 自定义 Hook 可以轻松复用状态逻辑
- 示例:创建
useFetch处理所有数据请求
-
函数式组件全面能力
- 无需类组件即可使用 state 和其他 React 特性
- 示例:
useState让函数组件拥有状态能力
-
更清晰的代码结构
- 按功能而非生命周期组织代码
- 示例:相关逻辑集中在一个
useEffect而非分散在多个生命周期方法
// 传统类组件 vs Hooks 函数组件对比
class Example extends React.Component {
state = { count: 0 };
componentDidMount() {
document.title = `点击了 ${this.state.count} 次`;
}
componentDidUpdate() {
document.title = `点击了 ${this.state.count} 次`;
}
render() {
return (
<button onClick={() => this.setState({ count: this.state.count + 1 })}>
点击 {this.state.count} 次
</button>
);
}
}
// Hooks 版本
function Example() {
const [count, setCount] = useState(0);
useEffect(() => {
document.title = `点击了 ${count} 次`;
}, [count]);
return (
<button onClick={() => setCount(count + 1)}>
点击 {count} 次
</button>
);
}
2. 核心 Hooks 使用场景
useState
- 场景:组件内部状态管理
- 最佳实践:
- 复杂状态建议拆分为多个
useState - 相关状态可考虑使用
useReducer
- 复杂状态建议拆分为多个
function Form() {
const [name, setName] = useState('');
const [email, setEmail] = useState('');
return (
<form>
<input value={name} onChange={e => setName(e.target.value)} />
<input value={email} onChange={e => setEmail(e.target.value)} />
</form>
);
}
useEffect
- 场景:副作用处理
- 数据获取
- 事件订阅
- 手动 DOM 操作
- 最佳实践:
- 明确依赖数组
- 清理副作用
function UserProfile({ userId }) {
const [user, setUser] = useState(null);
useEffect(() => {
let isMounted = true;
fetchUser(userId).then(data => {
if (isMounted) setUser(data);
});
return () => {
isMounted = false;
};
}, [userId]);
return <div>{user?.name}</div>;
}
useContext
- 场景:跨组件共享状态
- 最佳实践:
- 搭配
useReducer实现小型状态管理 - 避免过度使用导致组件难以维护
- 搭配
const ThemeContext = createContext('light');
function App() {
return (
<ThemeContext.Provider value="dark">
<Toolbar />
</ThemeContext.Provider>
);
}
function Toolbar() {
const theme = useContext(ThemeContext);
return <div style={{ background: theme === 'dark' ? '#333' : '#FFF' }} />;
}
useReducer
- 场景:复杂状态逻辑
- 多个子值相互依赖
- 下一个状态依赖前一个状态
- 最佳实践:
- 适合表单状态管理
- 替代多个
useState
function todosReducer(state, action) {
switch (action.type) {
case 'add':
return [...state, { text: action.text, completed: false }];
case 'toggle':
return state.map((todo, i) =>
i === action.index ? {...todo, completed: !todo.completed} : todo
);
default:
return state;
}
}
function TodoList() {
const [todos, dispatch] = useReducer(todosReducer, []);
return (
<>
{todos.map((todo, i) => (
<div key={i} onClick={() => dispatch({ type: 'toggle', index: i })}>
{todo.text}
</div>
))}
<button onClick={() => dispatch({ type: 'add', text: 'New todo' })}>
Add Todo
</button>
</>
);
}
3. 自定义 Hook 实践
-
提取通用逻辑
function useWindowSize() { const [size, setSize] = useState({ width: window.innerWidth, height: window.innerHeight }); useEffect(() => { const handleResize = () => { setSize({ width: window.innerWidth, height: window.innerHeight }); }; window.addEventListener('resize', handleResize); return () => window.removeEventListener('resize', handleResize); }, []); return size; } // 使用 function MyComponent() { const { width } = useWindowSize(); return <div>窗口宽度: {width}px</div>; } -
组合多个 Hook
function useUserData(userId) { const [user, setUser] = useState(null); const [loading, setLoading] = useState(false); const [error, setError] = useState(null); useEffect(() => { setLoading(true); fetchUser(userId) .then(data => { setUser(data); setError(null); }) .catch(err => setError(err)) .finally(() => setLoading(false)); }, [userId]); return { user, loading, error }; }
4. 性能优化技巧
-
useMemo
- 场景:计算昂贵的值
const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]); -
useCallback
- 场景:避免不必要的子组件重渲染
const handleClick = useCallback(() => { doSomething(a, b); }, [a, b]); -
React.memo
- 场景:组件浅比较
const MyComponent = React.memo(function MyComponent(props) { /* 渲染使用 props */ });
5. 注意事项
-
Hook 调用规则
- 只在最顶层调用 Hook
- 只在 React 函数中调用 Hook
-
依赖数组
- 确保包含所有依赖项
- 使用
eslint-plugin-react-hooks检查
-
性能陷阱
- 避免在渲染函数中执行高开销操作
- 合理拆分组件避免过度渲染
-
渐进采用策略
- 新组件优先使用 Hooks
- 旧组件逐步重构
6. 总结
React Hooks 通过以下方式改变了 React 开发范式:
- 逻辑复用更简单
- 代码组织更直观
- 组件测试更容易
- 性能优化更精准
对于新项目,建议全面采用 Hooks 开发;对于现有项目,可以逐步迁移。掌握 Hooks 是现代化 React 开发的必备技能。