# React Hooks 的优势和使用场景
## 1. 代码复用性提升
**自定义Hook**是Hooks最显著的优势,它允许我们将组件逻辑提取到可重用的函数中。相比传统的HOC或Render Props模式,自定义Hook更加直观且不会增加组件层级。
```jsx
// 自定义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>Window width: {width}px</div>;
}
2. 逻辑关注点分离
使用多个useEffect可以按照功能而非生命周期来组织代码,使相关代码保持在一起,提高可维护性。
function UserProfile({ userId }) {
// 用户数据获取
const [user, setUser] = useState(null);
useEffect(() => {
fetchUser(userId).then(setUser);
}, [userId]);
// 用户活动记录
const [activities, setActivities] = useState([]);
useEffect(() => {
fetchActivities(userId).then(setActivities);
}, [userId]);
// 相比class组件的分散逻辑,Hooks使相关代码更集中
}
3. 简化复杂组件
useReducer特别适合管理包含多个子值的复杂state逻辑,比useState更适用于复杂的state操作。
function todoReducer(state, action) {
switch (action.type) {
case 'add':
return [...state, action.payload];
case 'delete':
return state.filter(todo => todo.id !== action.payload);
default:
return state;
}
}
function TodoList() {
const [todos, dispatch] = useReducer(todoReducer, []);
const addTodo = text => {
dispatch({
type: 'add',
payload: { id: Date.now(), text }
});
};
// 相比多个useState,useReducer能更好管理复杂状态
}
4. 性能优化
useMemo和useCallback可以避免不必要的计算和子组件重渲染。
function ExpensiveComponent({ list }) {
const sortedList = useMemo(() => {
return list.sort((a, b) => a.value - b.value);
}, [list]); // 只有list变化时才重新计算
const handleClick = useCallback(() => {
console.log('Item clicked');
}, []); // 保持函数引用稳定
return <Child onClick={handleClick} data={sortedList} />;
}
5. 副作用管理
useEffect统一了生命周期方法,提供更清晰的副作用管理方式。
function DataFetcher({ url }) {
const [data, setData] = useState(null);
useEffect(() => {
let isMounted = true;
const fetchData = async () => {
const result = await fetch(url);
if (isMounted) setData(await result.json());
};
fetchData();
return () => {
isMounted = false; // 清理函数避免内存泄漏
};
}, [url]); // url变化时重新获取
}
6. 访问Context更简单
useContext让Context的使用更加简洁,无需嵌套Consumer。
const ThemeContext = createContext('light');
function ThemedButton() {
const theme = useContext(ThemeContext);
return <button style={{ background: theme }}>按钮</button>;
}
7. 替代class组件
Hooks几乎可以覆盖所有class组件的使用场景,使函数组件成为主流选择。
// 替代componentDidMount
useEffect(() => {
// 初始化逻辑
}, []);
// 替代componentDidUpdate
useEffect(() => {
// 更新逻辑
}, [dependencies]);
// 替代componentWillUnmount
useEffect(() => {
return () => {
// 清理逻辑
};
}, []);
8. 更好的TypeScript支持
函数组件配合Hooks能获得更完善的类型推断,减少类型声明代码。