React Hooks 是 React 16.8 引入的一组 API,用于在函数组件中使用 state 和其他 React 特性(例如生命周期方法、context 等)。Hooks 通过简洁的函数接口,解决了状态与 UI 的高度解耦,通过函数式编程范式实现更灵活 React 应用编码实现。
1. 优势
1.1. 简化状态管理和副作用处理
Hooks 如 useState 和 useEffect 使得在函数组件中处理状态和副作用变得更加直观和简洁。
javascript
import React, { useState, useEffect } from 'react';
function Counter() {
const [count, setCount] = useState(0);
useEffect(() => {
document.title = `You clicked ${count} times`;
}, [count]);
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>Click me</button>
</div>
);
}
1.2. 代码复用和组织
Hooks 提供了一种无需修改组件结构即可复用状态逻辑的方法。例如,可以创建自定义 Hook,将特定的状态逻辑封装起来,然后在多个组件中重用。
javascript
import { useState, useEffect } from 'react';
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 DisplayWidth() {
const width = useWindowWidth();
return <div>Window width: {width}</div>;
}
2. 常用的 React Hooks
2.1. useState
用于在函数组件中添加 state 变量。
javascript
const [count, setCount] = useState(0);
2.2. useEffect
用于在函数组件中执行副作用操作,如数据获取、订阅等。
javascript
useEffect(() => {
// 组件挂载时执行
return () => {
// 组件卸载时清理
};
}, [dependencies]); // 依赖数组
2.3. useContext
用于在函数组件中访问上下文。
javascript
const value = useContext(MyContext);
2.4. useReducer
用于管理复杂的 state 逻辑,类似于 Redux 的 reducer 概念。
javascript
const [state, dispatch] = useReducer(reducer, initialState);
2.5. useRef
用于访问 DOM 元素或保存不需要触发重新渲染的变量。
javascript
const inputRef = useRef(null);
2.6. useMemo和useCallback
用于性能优化,分别用于记忆化计算结果和记忆化函数。
javascript
const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
const memoizedCallback = useCallback(() => doSomething(a, b), [a, b]);
3. 自定义 Hook
自定义 Hook 是一种复用状态逻辑的方式,可以提取组件中重复的逻辑,封装成一个自定义 Hook,从而在多个组件中重用。
javascript
import { useState, useEffect } from 'react';
function useFetch(url) {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
fetch(url)
.then(response => response.json())
.then(data => {
setData(data);
setLoading(false);
});
}, [url]);
return { data, loading };
}
function App() {
const { data, loading } = useFetch('https://api.example.com/data');
if (loading) {
return <div>Loading...</div>;
}
return (
<div>
<pre>{JSON.stringify(data, null, 2)}</pre>
</div>
);
}