# React Hooks 的优势和使用场景
## 1. 代码复用性提升
通过自定义Hook可以轻松提取组件逻辑,使相同功能在不同组件间共享。传统高阶组件(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>窗口宽度: {width}px</div>;
}
2. 逻辑关注点分离
类组件中相关逻辑分散在各个生命周期方法中,Hook允许按照功能而非生命周期来组织代码。相同功能的代码可以集中管理,提高可读性。
function UserProfile({ userId }) {
// 用户数据相关逻辑
const [user, setUser] = useState(null);
useEffect(() => {
fetchUser(userId).then(setUser);
}, [userId]);
// 用户活动相关逻辑
const [activities, setActivities] = useState([]);
useEffect(() => {
fetchActivities(userId).then(setActivities);
}, [userId]);
// 渲染逻辑
if (!user) return <Loading />;
return (
<div>
<UserInfo user={user} />
<ActivityList activities={activities} />
</div>
);
}
3. 简化复杂组件
使用useReducer可以替代Redux管理局部复杂状态,避免过度状态提升。
function todosReducer(state, action) {
switch (action.type) {
case 'add':
return [...state, action.payload];
case 'toggle':
return state.map(todo =>
todo.id === action.payload
? { ...todo, completed: !todo.completed }
: todo
);
default:
return state;
}
}
function TodoApp() {
const [todos, dispatch] = useReducer(todosReducer, []);
const handleAdd = text => {
dispatch({ type: 'add', payload: { id: Date.now(), text } });
};
return (
<>
<TodoForm onSubmit={handleAdd} />
<TodoList
todos={todos}
onToggle={id => dispatch({ type: 'toggle', payload: id })}
/>
</>
);
}
4. 性能优化更精细
useMemo和useCallback可以精确控制重渲染和计算开销,避免不必要的性能损耗。
function ExpensiveComponent({ list, filter }) {
const filteredList = useMemo(() => {
return list.filter(item => item.includes(filter));
}, [list, filter]); // 只有当list或filter变化时重新计算
const handleClick = useCallback(() => {
console.log('Item clicked');
}, []); // 保持函数引用稳定
return (
<ul>
{filteredList.map(item => (
<li key={item} onClick={handleClick}>{item}</li>
))}
</ul>
);
}
5. 生命周期简化为副作用
useEffect统一处理副作用逻辑,替代componentDidMount、componentDidUpdate和componentWillUnmount。
function DataFetcher({ url }) {
const [data, setData] = useState(null);
const [error, setError] = useState(null);
useEffect(() => {
let isMounted = true;
const fetchData = async () => {
try {
const result = await fetch(url);
if (isMounted) setData(await result.json());
} catch (err) {
if (isMounted) setError(err);
}
};
fetchData();
return () => {
isMounted = false; // 清理函数
};
}, [url]); // url变化时重新获取
if (error) return <ErrorDisplay error={error} />;
if (!data) return <Loading />;
return <DataDisplay data={data} />;
}
6. 状态管理更灵活
useContext提供轻量级的状态共享方案,适合不需要Redux