React+TypeScript 如何将父组件props值累积存入子组件state数组
问题根因定位
- 缺少props变更判断:原代码在
componentDidUpdate中无判断直接执行setState,会触发新的重渲染,反过来再次进入componentDidUpdate,直接形成无限更新循环,导致页面卡死 - 未实现数组追加逻辑:原代码直接将单个的
this.props.faculty值赋值给state的faculties字段,完全没做数组拼接操作,自然无法得到预期的数组结构
类组件适配实现(匹配你原有生命周期写法的TS方案)
先完成对应的类型定义,避免TS类型报错:
// 子组件接收的props类型 interface ChildComponentProps { faculty: number; } // 子组件的state类型 interface ChildComponentState { faculties: number[]; }
核心组件逻辑调整如下:
class ChildComponent extends React.Component<ChildComponentProps, ChildComponentState> { constructor(props: ChildComponentProps) { super(props); this.state = { // 首次挂载时,把第一个传入的faculty值存入数组初始化 faculties: [props.faculty] } } componentDidUpdate(prevProps: ChildComponentProps) { // 仅当传入的faculty值和上一次props不一致时才执行更新,避免无限循环 if (prevProps.faculty !== this.props.faculty) { // 用函数式setState获取上一次的最新state,避免闭包拿到旧state的问题 this.setState(prevState => ({ // 用展开运算符把新值追加到原数组末尾,不修改原数组,符合React不可变更新要求 faculties: [...prevState.faculties, this.props.faculty] })) } } // 剩余组件渲染逻辑 render() { return <div>{this.state.faculties.join(',')}</div> } }
函数组件适配实现(结合TS的现代写法)
如果后续迁移到函数组件,可以用如下逻辑实现相同效果,避免重复追加:
import { useState, useEffect, useRef } from 'react'; interface ChildComponentProps { faculty: number; } const ChildComponent: React.FC<ChildComponentProps> = ({ faculty }) => { const [faculties, setFaculties] = useState<number[]>([]); // 用ref存储上一次处理过的faculty值,避免首次渲染时重复追加 const prevFacultyRef = useRef<number | undefined>(undefined); useEffect(() => { // 仅当faculty值发生变化时才执行追加 if (prevFacultyRef.current !== faculty) { setFaculties(prev => [...prev, faculty]); // 更新ref存储的最新处理值 prevFacultyRef.current = faculty; } }, [faculty]); return ( <div> {faculties.map(id => <span key={id}>{id}</span>)} </div> ) } export default ChildComponent;
核心注意事项
- 所有将props同步到state的逻辑,必须增加变更判断,绝对不能在更新生命周期/副作用内无判断直接执行
setState,否则会触发无限重渲染导致页面卡死 - 数组更新必须保持不可变原则,不要直接对state数组执行
push这类修改原数组的操作,要生成全新数组触发更新 - 如果业务需求是“只要父组件触发了prop传递(哪怕数值和上一次一致)也要追加”,可以把现有值比对的逻辑调整为记录父组件传递的唯一更新标识,适配需要重复追加相同数值的场景
- TS开发时要给props、state、内部引用变量明确标注类型,减少隐式类型报错
内容的提问来源于stack exchange,提问作者user7332667
相关产品推荐
相关产品推荐

