# React Hooks 的优势和使用场景
## 核心优势
### 1. 逻辑复用更简单
通过自定义 Hook 可以轻松复用状态逻辑,避免了高阶组件和 render props 的嵌套问题。
```jsx
// 自定义 Hook 示例
function useWindowWidth() {
const [width, setWidth] = useState(window.innerWidth);
useEffect(() => {
const handleResize = () => setWidth(window.innerWidth);
window.addEventListener('resize', handleResize);
return () => window.removeEventListener('resize', handleResize);
}, []);
return width;
}
// 在组件中使用
function MyComponent() {
const width = useWindowWidth();
return <div>窗口宽度: {width}px</div>;
}
2. 代码更简洁
消除了 class 组件的繁琐写法,函数组件可以完成所有功能。
// 类组件 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>
);
}
3. 更好的关注点分离
通过多个 useEffect 可以将相关逻辑组织在一起,而不是分散在不同的生命周期方法中。
function FriendStatus({ friendId }) {
const [status, setStatus] = useState(null);
// 订阅好友状态
useEffect(() => {
const handleStatusChange = (status) => setStatus(status);
ChatAPI.subscribe(friendId, handleStatusChange);
return () => ChatAPI.unsubscribe(friendId, handleStatusChange);
}, [friendId]);
// 更新文档标题
useEffect(() => {
document.title = `好友 ${friendId} 的状态: ${status}`;
}, [status, friendId]);
return <div>好友状态: {status}</div>;
}
主要使用场景
1. 状态管理
useState 适用于简单的组件状态管理:
function Counter() {
const [count, setCount] = useState(0);
const [step, setStep] = useState(1);
return (
<>
<button onClick={() => setCount(c => c + step)}>
增加 {step}
</button>
<input
type="number"
value={step}
onChange={e => setStep(Number(e.target.value))}
/>
当前值: {count}
</>
);
}
2. 副作用处理
useEffect 适用于数据获取、订阅、手动 DOM 操作等副作用:
function DataFetcher({ url }) {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(false);
const [error, setError] = useState(null);
useEffect(() => {
const fetchData = async () => {
try {
setLoading(true);
const response = await fetch(url);
const result = await response.json();
setData(result);
} catch (err) {
setError(err);
} finally {
setLoading(false);
}
};
fetchData();
}, [url]);
if (loading) return <div>加载中...</div>;
if (error) return <div>错误: {error.message}</div>;
return <pre>{JSON.stringify(data, null, 2)}</pre>;
}
3. 性能优化
useMemo 和 useCallback 可以优化性能,避免不必要的计算和渲染:
function ExpensiveComponent({ list, filter }) {
const filteredList = useMemo(() => {
console.log('重新计算过滤列表');
return list.filter(item => item.includes(filter));
}, [list, filter]);
const handleClick = useCallback(() => {
console.log('点击处理', filter);
}, [filter]);