React.js中如何非破坏性地对props传入的对象数组进行排序?
问题核心原因排查与解决方案
你遇到的控制台数据正确但DOM不更新的问题,基本都是以下几个常见原因导致,按优先级排查即可:
1. 最常见诱因:列表渲染的key使用了数组索引
React的Diff算法依赖key判断列表元素是否需要更新,如果你遍历数组时用index作为key,排序后每个元素的索引仍为0、1、2...,React会认为所有元素都没有变化,因此不会触发DOM更新。
修复方法:使用数组元素唯一的id作为key:
// 错误写法 {toddlers.map((item, index) => <div key={index}>{item.name}</div>)} // 正确写法 {toddlers.map(item => <div key={item.id}>{item.name}</div>)}
2. 渲染时用了props里的原始数组而非state里的排序后数组
如果你的render方法里仍然遍历this.props.getDaycare.toddlers,那无论state怎么更新,DOM都不会变化。
修复方法:渲染时优先取state里的排序后数组,需要恢复原始顺序时直接切换回原始数组即可:
render() { // 优先使用state中的排序后数组,为空则用原始数组 const renderList = this.state.newArray.length ? this.state.newArray : this.props.getDaycare.toddlers; return ( <div> <button onClick={this.sort}>按姓名排序</button> <button onClick={() => this.setState({newArray: []})}>恢复原始顺序</button> {renderList.map(toddler => ( <div key={toddler.id}> 姓名:{toddler.name} | 生日:{toddler.birthday} </div> ))} </div> ) }
3. 排序逻辑优化(非必需,但性能更好)
你当前的深拷贝逻辑是可用的,但针对仅调整数组顺序、不修改数组元素本身的场景,浅拷贝数组就足够满足非破坏性排序的要求,不需要用JSON深拷贝:
sort = () => { // 浅拷贝原始数组,避免修改原数组 const copiedList = [...this.props.getDaycare.toddlers]; // 对拷贝后的数组排序,localeCompare对中英文字符排序的兼容性更好 const sortedList = copiedList.sort((a, b) => a.name.localeCompare(b.name)); this.setState({ newArray: sortedList }, () => { // 回调中可确认state更新完成 console.log('排序完成', this.state.newArray); }) }
如果担心后续props的原始数组会变动,可在组件挂载时将原始数组存入state,恢复排序时直接取用即可:
constructor(){ super() this.state = { originalArray: [], newArray: [] } } componentDidMount() { // 组件挂载时缓存原始数组 this.setState({ originalArray: [...this.props.getDaycare.toddlers] }) } // 恢复原始排序方法 resetSort = () => { this.setState({ newArray: [...this.state.originalArray] }) }
内容的提问来源于stack exchange,提问作者Ifeoluwa Akinremi-Wade
相关产品推荐
相关产品推荐

