React中的钩子
从面试表达角度概览 React Hooks 的高频问法与回答线索。
#tech / dev / frame
#resource / react
#type / synthesis
#status / growing
React 钩子(Hooks)从被面试者角度解析
[!info] related notes
作为被面试者,在回答React钩子相关问题时,我会从以下几个方面进行阐述:
1. 钩子的基本概念
首先我会解释钩子是什么:
- 钩子是React 16.8引入的新特性
- 允许我们在函数组件中使用state和其他React特性
- 目的是解决类组件的几个问题:组件间状态逻辑难以复用、复杂组件难以理解、类学习成本高等
2. 常用内置钩子
useState
const [state, setState] = useState(initialState);
- 用于在函数组件中添加局部state
- 返回一个state值和一个更新state的函数
- 面试中可能会问:为什么setState是异步的?(为了性能优化,批量更新)
useEffect
useEffect(() => {
// 副作用操作
return () => {
// 清理函数
};
}, [dependencies]);
- 用于处理副作用(数据获取、订阅、手动DOM操作等)
- 相当于类组件中的componentDidMount、componentDidUpdate和componentWillUnmount的组合
- 面试常问:依赖数组的作用?空数组和没有数组的区别?
useContext
const value = useContext(MyContext);
- 用于在函数组件中订阅React context
- 避免在函数组件中嵌套使用Consumer
useReducer
const [state, dispatch] = useReducer(reducer, initialArg, init);
- useState的替代方案,适合复杂state逻辑
- 面试可能会问:useReducer和Redux的区别?
useCallback & useMemo
const memoizedCallback = useCallback(() => {
doSomething(a, b);
}, [a, b]);
const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
- 用于性能优化
- useCallback缓存函数,useMemo缓存值
- 面试常问:什么情况下需要使用它们?
useRef
const refContainer = useRef(initialValue);
- 用于访问DOM节点或保存可变值
- 与createRef的区别?(useRef在组件生命周期内保持引用不变)
3. 自定义钩子
- 自定义钩子是一个以”use”开头的函数
- 可以将组件逻辑提取到可重用的函数中
- 示例:
function useFriendStatus(friendID) {
const [isOnline, setIsOnline] = useState(null);
useEffect(() => {
// 订阅好友状态逻辑
return () => {
// 取消订阅
};
}, [friendID]);
return isOnline;
}
4. 钩子使用规则
我会强调两条重要规则:
- 只在React函数组件或自定义钩子中调用钩子
- 只在最顶层使用钩子(不在循环、条件或嵌套函数中调用)
面试官可能会问为什么有这些规则?(React依赖钩子调用的顺序来正确关联state)
5. 钩子与类组件的对比
我会准备一些对比点:
- 代码更简洁,逻辑更集中
- 更容易复用状态逻辑(自定义钩子vs HOC/render props)
- 没有this绑定问题
- 更细粒度的生命周期控制
6. 常见面试问题准备
我会准备回答以下常见问题:
- 为什么需要钩子?解决了什么问题?
- useEffect和useLayoutEffect的区别?
- 如何避免useEffect的无限循环?
- 如何在钩子中实现shouldComponentUpdate?(React.memo + useMemo/useCallback)
- 钩子的性能优化策略
- 如何测试使用钩子的组件?
7. 实践经验
如果有实际项目经验,我会举例说明:
- 在什么项目中使用了哪些钩子
- 解决了什么具体问题
- 遇到了什么坑,如何解决的
通过这样系统性的准备,我相信能够全面展示对React钩子的理解和实际应用能力。