2026年03月27日-React Hooks最佳实践 React Hooks最佳实践与性能优化 React Hooks自16.8版本引入以来,彻底改变了函数组件的开发方式。掌握Hooks的最佳实践,能够编写更简洁、高效的React应用。 核心Hooks使用 useState - 状态管理: useEffect - 副作用处理: useContext - 状态共享: useReducer - 复杂状态逻辑: 自定义Hooks 封装可复用逻辑: 数据获取Hook: 性能优化 useMemo - 缓存计算结果: useCallback - 缓存函数引用: React.
React Hooks自16.8版本引入以来,彻底改变了函数组件的开发方式。掌握Hooks的最佳实践,能够编写更简洁、高效的React应用。
useState - 状态管理:
import { useState } from 'react'; function Counter() { const [count, setCount] = useState(0); // 函数式更新,避免闭包陷阱 const increment = () => { setCount(prev => prev + 1); }; return ( <div> <p>计数:{count}</p> <button onClick={increment}>增加</button> </div> ); }
useEffect - 副作用处理:
useEffect(() => { // 订阅、定时器、手动DOM更新等副作用 const subscription = dataSource.subscribe(); // 清理函数,组件卸载时执行 return () => { subscription.unsubscribe(); }; }, [dataSource]); // 依赖项数组
useContext - 状态共享:
const ThemeContext = createContext('light'); function App() { return ( <ThemeContext.Provider value="dark"> <Toolbar /> </ThemeContext.Provider> ); } function Toolbar() { const theme = useContext(ThemeContext); return <div className={theme}>工具栏</div>; }
useReducer - 复杂状态逻辑:
const initialState = { count: 0 }; function reducer(state, action) { switch (action.type) { case 'increment': return { count: state.count + 1 }; case 'decrement': return { count: state.count - 1 }; default: throw new Error(); } } function Counter() { const [state, dispatch] = useReducer(reducer, initialState); return ( <> <p>计数:{state.count}</p> <button onClick={() => dispatch({ type: 'increment' })}> 增加 </button> </> ); }
封装可复用逻辑:
// useWindowSize.js 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 ResponsiveComponent() { const { width, height } = useWindowSize(); return ( <div> 窗口大小:{width} x {height} </div> ); }
数据获取Hook:
function useFetch(url) { const [data, setData] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); useEffect(() => { const fetchData = async () => { try { const response = await fetch(url); const json = await response.json(); setData(json); } catch (err) { setError(err); } finally { setLoading(false); } }; fetchData(); }, [url]); return { data, loading, error }; }
useMemo - 缓存计算结果:
function ExpensiveComponent({ items, filter }) { // 缓存过滤结果,仅当items或filter变化时重新计算 const filteredItems = useMemo(() => { return items.filter(item => item.category === filter); }, [items, filter]); return <div>{/* 渲染filteredItems */}</div>; }
useCallback - 缓存函数引用:
function ParentComponent() { const [count, setCount] = useState(0); // useCallback避免子组件不必要的重渲染 const handleClick = useCallback(() => { console.log('点击'); }, []); // 空依赖数组,函数引用永远不变 return <ChildButton onClick={handleClick} />; }
React.memo - 组件记忆化:
const MemoComponent = React.memo(function MyComponent({ name, age }) { console.log('组件渲染'); return <div>{name} - {age}</div>; }, (prevProps, nextProps) => { // 自定义比较函数 return prevProps.name === nextProps.name && prevProps.age === nextProps.age; });
闭包陷阱:
// 错误示例 function Counter() { const [count, setCount] = useState(0); useEffect(() => { const timer = setInterval(() => { console.log(count); // 永远输出0 }, 1000); return () => clearInterval(timer); }, []); // 空依赖导致count永远是初始值 // 解决方案1:添加依赖 useEffect(() => { const timer = setInterval(() => { console.log(count); }, 1000); return () => clearInterval(timer); }, [count]); // 解决方案2:使用函数式更新 useEffect(() => { const timer = setInterval(() => { setCount(prev => prev + 1); }, 1000); return () => clearInterval(timer); }, []); }
无限循环渲染:
// 错误示例 function Component() { const [data, setData] = useState(null); useEffect(() => { fetchData().then(result => { setData(result); // 触发重渲染 }); }); // 缺少依赖数组,每次渲染都执行 // 正确示例 useEffect(() => { fetchData().then(result => { setData(result); }); }, []); // 空依赖数组,仅执行一次 }
useReducer + useContext(替代Redux):
const TodoContext = createContext(); function TodoProvider({ children }) { const [state, dispatch] = useReducer(todoReducer, initialState); return ( <TodoContext.Provider value={{ state, dispatch }}> {children} </TodoContext.Provider> ); } function useTodos() { const context = useContext(TodoContext); if (!context) { throw new Error('useTodos must be used within TodoProvider'); } return context; } // 使用 function TodoApp() { const { state, dispatch } = useTodos(); const addTodo = (text) => { dispatch({ type: 'ADD_TODO', payload: text }); }; return <div>{/* 渲染todos */}</div>; }
Zustand轻量状态管理:
import create from 'zustand'; const useStore = create((set) => ({ count: 0, increment: () => set((state) => ({ count: state.count + 1 })), decrement: () => set((state) => ({ count: state.count - 1 })), })); function Counter() { const { count, increment } = useStore(); return <button onClick={increment}>{count}</button>; }
仅在顶层调用:
// ❌ 错误:在条件语句中使用 function BadComponent() { if (someCondition) { const [state, setState] = useState(0); } } // ✅ 正确:始终在顶层调用 function GoodComponent() { const [state, setState] = useState(0); if (someCondition) { // 使用state } }
仅在React函数中调用:
// ✅ React函数组件 function MyComponent() { const [state, setState] = useState(0); return <div>{state}</div>; } // ✅ 自定义Hook function useMyHook() { const [state, setState] = useState(0); return state; } // ❌ 错误:在普通JavaScript函数中调用 function regularFunction() { const [state, setState] = useState(0); // 报错 }
ESLint插件强制Hooks规则:
{ "eslintConfig": { "extends": ["react-app"], "rules": { "react-hooks/rules-of-hooks": "error", "react-hooks/exhaustive-deps": "warn" }, "plugins": ["react-hooks"] } }
React DevTools Profiler:
React Hooks让函数组件更强大、更简洁。遵循Hooks规则,合理使用性能优化技巧,避免常见陷阱,能够构建高性能的React应用。结合自定义Hooks封装可复用逻辑,提高代码复用性和可维护性。