使用useState钩子初始化的对象数组无法排序问题排查与解决
React数组排序后页面不更新的原因及解决方法
问题场景
你通过useState声明对象数组,用map渲染列表,点击排序按钮后控制台显示数组已排序,但页面列表完全没有更新。
问题根源
JavaScript的Array.sort()是原地排序方法——它会直接修改调用它的原数组,不会返回新数组。你在setItems里返回的sortedItems其实就是原状态数组的同一个引用,React对比新旧状态时发现引用没变化,就不会触发组件重渲染,所以页面不会同步更新。
正确实现方式
核心思路:排序前先复制原数组,让setItems接收一个新的数组引用,这样React就能检测到状态变化并更新页面。
方式一:扩展运算符复制数组
const sortByTitleAscending = () => { setItems((prevItems) => { // 复制原数组后再排序,返回新数组 return [...prevItems].sort((a, b) => a.title.localeCompare(b.title)); }); } const sortByTitleDescending = () => { setItems((prevItems) => { return [...prevItems].sort((a, b) => b.title.localeCompare(a.title)); }); }
方式二:Array.slice()浅拷贝数组
slice()不传参数时会返回原数组的浅拷贝:
const sortByTitleAscending = () => { setItems((prevItems) => { return prevItems.slice().sort((a, b) => a.title.localeCompare(b.title)); }); }
完整修正代码
function App() { const [items, setItems] = React.useState([{id: 1, title: "Example Item"}, {id: 2, title: "Another example item"}]) const sortByTitleAscending = () => { setItems((prevItems) => [...prevItems].sort((a, b) => a.title.localeCompare(b.title))); } const sortByTitleDescending = () => { setItems((prevItems) => [...prevItems].sort((a, b) => b.title.localeCompare(a.title))); } return ( <div> <h1>Hello World!</h1> <p><button onClick={sortByTitleAscending}>Sort by ascending</button></p> <p><button onClick={sortByTitleDescending}>Sort by descending</button></p> <ul> {items.map(item => ( <li key={item.id}>{item.title}</li> ))} </ul> </div> ); } ReactDOM.render(<App/>, document.getElementById('root'));
内容的提问来源于stack exchange,提问作者Harish
相关产品推荐
相关产品推荐

