别再只问一个AI了:多模型交叉验证的常见误区及避坑指南
2026-06-23
2026-06-24 0
React类组件迁移至函数组件需五步:1. 替换类声明为函数并提取JSX;2. 用useState替代this.state,注意对象初始化;3. 用useEffect替代生命周期,区分挂载、更新、卸载逻辑;4. 重构事件处理器为箭头函数;5. 更新测试用例,改用@testing-library/react并模拟交互。

你需要把一个正在运行的 React 类组件项目迁移到函数式组件结构,同时确保所有单元测试仍能通过——不是只改 JSX,而是让状态、生命周期、事件处理全部正确映射,并验证测试覆盖率不下降。
打开目标类组件文件(如 Counter.js),删除 class Counter extends Component 和 render() { ... } 模板结构。用函数声明替代:const Counter = () => {,直接把原 render() 内部的 JSX 复制到 return 语句中。注意:此时不要删 constructor 或 state 初始化代码,先保留——它们将被后续步骤覆盖。
这一步操作起来很简单,直接把文件拖进去就行。但必须确认 JSX 中没有残留 this.props 或 this.state 引用,否则会报 ReferenceError。
找到类组件中的 constructor(props) 或 state = { ... } 声明,逐个提取键名(如 count、loading、error)。在函数组件顶部,为每个键调用 useState:
const [count, setCount] = useState(0);const [loading, setLoading] = useState(false);const [error, setError] = useState(null);
【不要用 useState(null) 初始化对象】——如果原始 state 是对象(如 { user: null, permissions: [] }),必须传入完整初始值:useState({ user: null, permissions: [] }),否则后续解构或属性访问会出错。
接着批量替换所有 this.setState({ count: newCount }) 为 setCount(newCount);若更新依赖前值(如 this.setState(prev => ({ count: prev.count + 1 }))),改为 setCount(prev => prev + 1)。
方法一:替换 componentDidMount
把 componentDidMount() { fetchData(); } 改为:
useEffect(() => { fetchData(); }, []);
注意空依赖数组 [] 必须显式写出,漏掉会导致每次渲染都执行。
方法二:替换 componentDidUpdate + 条件判断
若原逻辑是 componentDidUpdate(prevProps) { if (prevProps.id !== this.props.id) { fetchItem(this.props.id); } },则写成:
useEffect(() => { fetchItem(props.id); }, [props.id]);
React 会自动比对 props.id 的引用变化,无需手动判断。
方法三:替换 componentWillUnmount
把 componentWillUnmount() { clearTimeout(timerId); } 改为:
useEffect(() => { const timerId = setTimeout(...); return () => clearTimeout(timerId); }, []);
清理函数必须作为 useEffect 的返回值,且仅在组件卸载或依赖变更时触发。
删除所有 this.handleClick = this.handleClick.bind(this) 绑定语句。将类方法(如 handleClick() { ... })改为函数常量声明:
const handleClick = () => { setCount(prev => prev + 1); };
箭头函数天然绑定作用域,无需 bind。但注意:若方法接收参数且需内联传参(如 onClick={() => onDelete(item.id)}),不要提前执行——写成 onClick={() => onDelete(item.id)} 即可,避免 onClick={onDelete(item.id)} 这种立即调用写法,否则每次渲染都会触发删除。
对于异步方法,直接用 async/await 声明即可:
const handleSubmit = async (e) => { e.preventDefault(); await api.submit(formData); };
第一步:执行 npm test 或 yarn test,观察失败用例列表。
第二步:定位第一个失败测试,通常是“renders correctly”快照测试。打开对应测试文件(如 Counter.test.js),检查是否还在用 enzyme 的 shallow 或 mount 调用类组件。如果是,把 shallow( 改为 render((使用 @testing-library/react)。
第三步:修复断言中对实例方法的调用。例如原测试有 wrapper.instance().handleClick(),这已失效——改为模拟用户交互:fireEvent.click(screen.getByRole('button')),再断言状态变化。
第四步:检查 useEffect 相关测试。若原测试用 jest.useFakeTimers() 控制 componentDidMount 中的定时器,现在需确保 act(async () => {...}) 包裹异步更新,否则 waitFor 可能超时。
第五步:逐个重跑失败测试,直到 ✓ All tests pass 显示在终端。