React 的函数组件(Function Component)在引入 Hooks 后,可以实现类组件的所有功能,并且代码更简洁、逻辑更复用。以下是 React 函数组件的高级用法详解:
1. 核心 Hooks 进阶
(1) useState - 状态管理
- 惰性初始化:避免每次渲染都计算初始值。
jsx
const [state, setState] = useState(() => { const initialValue = computeExpensiveValue(); // 只执行一次 return initialValue; }); - 函数式更新:依赖前一个状态时使用。
jsx
setCount(prevCount => prevCount + 1);
(2) useEffect - 副作用管理
- 依赖项优化:
- 空数组
[]:仅在组件挂载/卸载时执行(类似componentDidMount+componentWillUnmount)。 - 特定依赖
[dep]:仅在dep变化时执行。
jsxuseEffect(() => { const subscription = props.source.subscribe(); return () => subscription.unsubscribe(); // 清理函数 }, [props.source]); - 空数组
- 异步处理:
jsx
useEffect(() => { const fetchData = async () => { const result = await axios.get('/api/data'); setData(result.data); }; fetchData(); }, []);
(3) useMemo & useCallback - 性能优化
useMemo:缓存计算结果,避免重复计算。jsxconst memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);useCallback:缓存函数,避免子组件不必要的重渲染。jsxconst handleClick = useCallback(() => { console.log('Clicked:', id); }, [id]);
2. 自定义 Hooks
封装可复用的逻辑(替代 HOC 或 Render Props)。
示例:自定义 useFetch Hook
jsx
function useFetch(url) {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
const fetchData = async () => {
const response = await fetch(url);
const result = await response.json();
setData(result);
setLoading(false);
};
fetchData();
}, [url]);
return { data, loading };
}
// 使用
function MyComponent() {
const { data, loading } = useFetch('/api/data');
if (loading) return <div>Loading...</div>;
return <div>{data}</div>;
}
3. Context + useReducer - 状态管理
替代 Redux 的轻量级方案。
(1) 创建 Context
jsx
const MyContext = React.createContext();
function App() {
const [state, dispatch] = useReducer(reducer, initialState);
return (
<MyContext.Provider value={{ state, dispatch }}>
<ChildComponent />
</MyContext.Provider>
);
}
(2) 定义 Reducer
jsx
function reducer(state, action) {
switch (action.type) {
case 'INCREMENT':
return { count: state.count + 1 };
case 'DECREMENT':
return { count: state.count - 1 };
default:
return state;
}
}
(3) 在子组件中使用
jsx
function ChildComponent() {
const { state, dispatch } = useContext(MyContext);
return (
<button onClick={() => dispatch({ type: 'INCREMENT' })}>
Count: {state.count}
</button>
);
}
4. Refs 与 DOM 操作
(1) useRef - 获取 DOM 或保存可变值
jsx
function TextInput() {
const inputRef = useRef(null);
useEffect(() => {
inputRef.current.focus(); // 自动聚焦
}, []);
return <input ref={inputRef} />;
}
(2) forwardRef - 转发 Ref 到子组件
jsx
const FancyInput = React.forwardRef((props, ref) => (
<input ref={ref} className="fancy-input" />
));
function Parent() {
const inputRef = useRef();
return <FancyInput ref={inputRef} />;
}
5. 高级模式
(1) 动态导入与代码分割(React.lazy)
jsx
const LazyComponent = React.lazy(() => import('./LazyComponent'));
function App() {
return (
<Suspense fallback={<div>Loading...</div>}>
<LazyComponent />
</Suspense>
);
}
(2) 错误边界(Error Boundaries)
jsx
class ErrorBoundary extends React.Component {
state = { hasError: false };
static getDerivedStateFromError(error) {
return { hasError: true };
}
render() {
if (this.state.hasError) {
return <h1>Something went wrong.</h1>;
}
return this.props.children;
}
}
// 使用
<ErrorBoundary>
<BuggyComponent />
</ErrorBoundary>
6. 性能优化技巧
React.memo:避免不必要的子组件重渲染。jsxconst MemoizedComponent = React.memo(MyComponent);- 虚拟列表(
react-window):优化长列表渲染。jsximport { FixedSizeList as List } from 'react-window'; <List height={600} itemCount={1000} itemSize={35}> {({ index, style }) => <div style={style}>Item {index}</div>} </List>
总结
| 功能 | 实现方式 |
|---|---|
| 状态管理 | useState, useReducer |
| 副作用 | useEffect, useLayoutEffect |
| 性能优化 | useMemo, useCallback, React.memo |
| 复用逻辑 | 自定义 Hooks |
| 跨组件通信 | Context + useContext |
| DOM 操作 | useRef, forwardRef |
掌握这些高级用法后,可以更高效地开发复杂 React 应用,同时保持代码的可维护性和性能。
