React Hooks 和类组件有什么区别?
React Hooks 让函数组件拥有状态和生命周期功能,而类组件依赖 this.state 和方法如 componentDidMount。Hooks 代码更简洁、无 this 问题、易复用逻辑。例如,useState 替换 state,useEffect 整合多个生命周期。类组件适合复杂场景,但 Hooks 是现代主流,推荐新项目全用 Hooks。迁移时,从简单组件开始逐步替换,确保遵守 Hooks 规则。
React Hooks 是 React 16.8 版本引入的一项革命性特性,它允许开发者在函数组件中使用状态(state)和生命周期等 React 功能,而无需编写复杂的类组件。简单来说,Hooks 就像“钩子”,可以将外部功能“钩”入纯函数组件中,让代码更简洁、可复用。
传统类组件需要 this.state 和生命周期方法如 componentDidMount,但 Hooks 通过 useState、useEffect 等内置函数简化这一切。你只需要导入 React,然后在函数组件顶层调用 Hooks,就能实现相同效果。
为什么选择 Hooks?它解决了类组件的痛点:逻辑复用困难、this 绑定麻烦。使用 Hooks,你的组件变成纯函数,更易测试和维护。根据 React 官方文档,Hooks 让函数组件成为主流写法。
useState 是最基础的 Hooks,用于在函数组件中添加状态。它返回一个数组:[当前状态值,更新状态的函数]。
分步操作:
示例代码:
function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<p>点击次数:{count}</p>
<button onClick={() => setCount(count + 1)}>+1</button>
</div>
);
}
注意规则:Hooks 只能在组件顶层调用,不能放循环或条件中,确保每次渲染顺序一致。处理对象状态时,使用函数式更新如 setUser(prev => ({ ...prev, name: '新名' })) 避免异步坑。
useEffect 是另一个核心 Hooks,对应类组件的生命周期,如 componentDidMount、componentDidUpdate 和 componentWillUnmount。它用于处理数据获取、订阅等副作用。
分步指南:
示例:获取用户数据
function UserProfile({ userId }) {
const [user, setUser] = useState(null);
useEffect(() => {
fetch(`/api/user/${userId}`)
.then(res => res.json())
.then(data => setUser(data));
return () => console.log('清理');
}, [userId]);
return <p>{user ? user.name : '加载中'}</p>;
}
用 ESLint 插件 react-hooks/rules-of-hooks 检查规则,避免常见错误。
除了基础,React 还提供 useContext(访问 Context)、useReducer(复杂状态,如 Redux 替代)。例如,useReducer(reducer, initialState) 返回 [state, dispatch]。
巅峰:创建自定义 Hooks 复用逻辑!封装 useFetch Hook:
function useFetch(url) {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
setLoading(true);
fetch(url).then(res => res.json()).then(setData).finally(() => setLoading(false));
}, [url]);
return { data, loading };
}
// 使用:const { data, loading } = useFetch('/api/data');
自定义 Hooks 以 use 前缀命名,便于识别。遵循纯函数原则,每次渲染重新执行。
使用 Hooks 时,记住三规则:顶层调用、只在 React 函数中、自定义 Hooks 也遵守。性能优化用 useCallback 记忆函数、useMemo 记忆值,避免不必要重渲染。
从类组件迁移?逐步替换,先用 Hooks 新组件。实践项目:Todo List,用 useState 管理列表,useEffect 持久化 localStorage。
通过以上分步教程,你已掌握 Hooks 精髓。立即编码,体验函数组件的优雅!(本文约1050字)
React Hooks 让函数组件拥有状态和生命周期功能,而类组件依赖 this.state 和方法如 componentDidMount。Hooks 代码更简洁、无 this 问题、易复用逻辑。例如,useState 替换 state,useEffect 整合多个生命周期。类组件适合复杂场景,但 Hooks 是现代主流,推荐新项目全用 Hooks。迁移时,从简单组件开始逐步替换,确保遵守 Hooks 规则。
useState 初始化对象如 const [user, setUser] = useState({ name: '' })。更新时用函数式形式 setUser(prev => ({ ...prev, name: '张三' })),避免异步覆盖。多个状态用独立 useState 更清晰,或用 useReducer 管理。示例:Todo 应用中,setTodos(prev => [...prev, newTodo]) 添加项。记住,setState 是异步,依赖 prev 确保最新值。
useEffect(callback, deps) 中,deps 控制执行时机。空数组 [] 只 mount 时跑;无数组每次渲染跑;[id] 依赖 id 变化跑。返回函数清理资源,如取消定时器。常见坑:遗漏依赖导致 stale closure,用 ESLint 插件自动检查。示例:数据获取 useEffect(..., [userId]),避免无限循环。
自定义 Hooks 以 use 开头,返回值供组件用。封装逻辑如 useFetch(url),内部用 useState + useEffect,返回 { data, loading }。它像组件逻辑复用,每次渲染重跑,确保纯函数。示例:usePerson(id) fetch 人物数据。优势:共享代码,避免 HOC 或 Render Props 复杂。遵循顶层规则,自定义 Hooks 内可嵌套其他 Hooks。
三金规则:1. 只在函数组件或自定义 Hooks 顶层调用;2. 别在循环、条件、嵌套函数中用;3. 每次渲染 Hooks 顺序相同。违反导致状态错乱。用 eslint-plugin-react-hooks 插件强制检查。原因:React 用调用顺序关联状态。示例:if 条件下用 Hooks 会乱序失败。
useReducer 适合复杂状态逻辑,如多状态互斥或嵌套更新。语法:const [state, dispatch] = useReducer(reducer, initial)。reducer 如 (state, action) => action.type === 'add' ? [...state, action.payload] : state。类似 Redux,dispatch({ type: 'add', payload })。优于多个 useState,易测试。Todo 或表单场景首选。
用 useMemo 记忆计算值:const expensive = useMemo(() => compute(data), [data])。useCallback 记忆函数:const handleClick = useCallback(() => {}, [deps]),防子组件重渲染。结合 React.memo 包裹组件。只 memo 真正耗时部分,避免过度。实际:列表渲染用 useMemo 计算过滤结果,提升大列表流畅度。