如何强制React新建子组件触发componentDidMount而不复用现有组件?
解决方案核心原理
React的虚拟DOM Diff算法在更新列表时,会根据key属性判断是否可以复用现有组件实例。你遇到的组件复用、componentDidMount不触发的问题,本质是没有给子组件设置唯一标识的key,导致React默认按列表位置复用组件。
要实现对应不同person数据的子组件都从头创建并触发componentDidMount,只需要给每个SinglePersonThumbnail设置唯一的、和person数据绑定的key属性即可。
代码优化建议
第一步:修正父组件的错误实践
不要把生成的子组件直接存在state中,改为存储后端返回的原始person数据列表,在render阶段再动态生成子组件,避免state冗余:
class ComponentManager extends Component { constructor(props) { super(props); this.state = { // 存储原始人员数据,而非生成好的组件 persons: [] } } componentDidMount() { this.importPersonsIds(); } importPersonsIds(sortingMode) { // 从后端拉取数据后,把原始person列表存在state里,不要提前生成组件 fetchPersonsFromApi(sortingMode).then(personsData => { this.setState({ persons: personsData }) }) } render() { return( <div> <button onClick={()=>{this.importPersonsIds("SORT_BY_AGE")}}>按年龄排序</button> <button onClick={()=>{this.importPersonsIds("SORT_BY_NAME")}}>按姓名排序</button> <div> {/* 渲染时动态生成子组件,给每个子组件绑定person的唯一id作为key */} {this.state.persons.map(person => ( <SinglePersonThumbnail key={person.id} id={person.id} /> ))} </div> </div> ); } }
第二步:简化子组件逻辑
因为现在key和person id绑定,只要id变化,React就会销毁旧组件、创建新组件,自动触发componentDidMount,所以可以删掉冗余的componentWillReceiveProps逻辑:
class SinglePersonThumbnail extends Component { constructor(props) { super(props); this.state = { photoUrl : undefined, personsName : undefined } } componentDidMount() { // 只有组件全新创建时才会触发,不需要再处理props更新的情况 this.importDataAndPhotoForPerson(this.props.id); } importDataAndPhotoForPerson(id) { // 拉取人员信息和照片链接更新state } render() { // 按state渲染照片和姓名即可 } }
特殊场景的极端方案
如果遇到需要对整个列表强制全量重建的场景(比如全局刷新所有缩略图,哪怕id没变也要重新拉取数据),可以给列表的父容器加一个key,每次需要重建时更新这个key的值即可:
// 父组件state新增一个refreshKey字段 this.state = { persons: [], refreshKey: 0 } // 需要全量重建时更新refreshKey refreshAllThumbnails = () => { this.setState(prev => ({ refreshKey: prev.refreshKey + 1 })) } // 渲染时给列表容器绑定key <div key={this.state.refreshKey}> {this.state.persons.map(person => ( <SinglePersonThumbnail key={person.id} id={person.id}/> ))} </div>
内容的提问来源于stack exchange,提问作者user15337753
相关产品推荐
相关产品推荐

