面试题答案
一键面试相同点
- 处理副作用:两者都有能力处理副作用操作,如数据获取、订阅事件或手动变更 DOM 等。
- 状态管理:都能进行状态管理,在组件内部存储和更新数据,以驱动 UI 变化。
不同点
- 处理副作用:
- React 类组件生命周期:通过
componentDidMount
、componentDidUpdate
和componentWillUnmount
等生命周期方法来处理副作用。在componentDidMount
中执行初始化副作用操作,在componentDidUpdate
中根据前后状态变化决定是否重新执行副作用,componentWillUnmount
用于清理副作用。但这些方法耦合度较高,复杂组件中可能导致代码难以维护。 - React Hooks:使用
useEffect
Hook 处理副作用。可以通过在依赖数组中指定依赖项,精确控制副作用的执行时机。依赖数组为空时,类似componentDidMount
;依赖数组有值时,类似componentDidUpdate
;在返回函数中进行清理操作,类似componentWillUnmount
。逻辑更清晰,易于理解和维护。
- React 类组件生命周期:通过
- 状态管理:
- React 类组件生命周期:状态存储在
this.state
中,通过setState
方法更新状态。但setState
可能存在异步更新问题,且在复杂场景下,状态更新逻辑可能变得复杂。 - React Hooks:使用
useState
Hook 进行状态管理,简单直接。每次调用useState
返回的setState
函数更新状态都是同步的,便于理解和调试。同时可以使用多个useState
分别管理不同状态,避免状态逻辑耦合。
- React 类组件生命周期:状态存储在
- 代码结构与复用性:
- React 类组件生命周期:代码结构基于类,复用逻辑较复杂,通常需要使用高阶组件(HOC)或 Render Props 模式,这可能导致组件嵌套过深,增加复杂度。
- React Hooks:基于函数,复用逻辑可通过自定义 Hooks 实现,代码简洁且复用性高,不会产生嵌套地狱问题。
适合使用 React Hooks 重构类组件的场景
- 简单状态管理场景:如表单输入、开关切换等简单状态控制。例如一个登录表单,使用
useState
可以很简洁地管理输入框的值和提交状态,相比类组件的this.state
和setState
更加直观。 - 副作用操作场景:数据获取、事件监听等副作用逻辑。例如在组件挂载时获取用户信息,使用
useEffect
可以清晰地定义副作用操作和清理逻辑,替代类组件中分散在多个生命周期方法中的代码。 - 逻辑复用场景:如果有多个组件需要复用相同逻辑,如权限验证逻辑,通过自定义 Hooks 可以轻松实现逻辑复用,避免在类组件中使用 HOC 或 Render Props 带来的嵌套问题。
不适合使用 React Hooks 重构类组件的场景
- 复杂大型项目且类组件结构稳定:如果项目已经成熟,类组件结构复杂但运行稳定,重构可能带来较大风险,投入产出比不高。因为重构可能涉及到大量代码修改,容易引入新的 bug。
- 对 React 旧版本兼容性要求高:如果项目需要兼容 React 旧版本(如 React 16.7 之前),无法使用 Hooks,因为 Hooks 是从 React 16.8 开始引入的。
重构过程中可能遇到的挑战及解决方案
- 状态迁移挑战:类组件状态管理逻辑迁移到
useState
可能遇到困难,尤其是复杂状态逻辑。例如,类组件中状态更新依赖前一个状态,在useState
中应使用函数形式的setState
。解决方案是仔细梳理原状态更新逻辑,按照useState
的规则进行改写,必要时可以在useEffect
中处理复杂状态更新逻辑。 - 副作用清理挑战:类组件中
componentWillUnmount
清理副作用,在 Hooks 中使用useEffect
返回函数清理。但如果原逻辑复杂,可能遗漏清理逻辑。解决方案是对原类组件的副作用逻辑进行详细分析,确保在useEffect
返回函数中正确清理所有副作用,如取消订阅、清除定时器等。 - 上下文(Context)使用挑战:类组件通过
this.context
使用上下文,Hooks 中使用useContext
。在重构时可能出现上下文使用不当问题。解决方案是理解useContext
的使用方式,确保正确获取和更新上下文数据,注意上下文更新可能引发的组件重新渲染问题。