React自定义表格点击表头排序不生效、排序结果混乱问题求助
React自定义表格排序问题解决方案
问题根因
- 最早点击表头不触发重渲染的原因:最初排序时直接修改了原posts数组,没有生成新的数组引用,React浅比较state时认为状态无变化,不会触发重渲染,你后续新增的
[...currPosts]拷贝数组的操作已经解决了这个问题。 - 后续排序混乱的核心原因1:
keySortMap直接定义在组件函数体中,每次组件重渲染都会被重新初始化,上次点击设置的排序状态无法持久化存储,每次点击都会回到初始值0。 - 后续排序混乱的核心原因2:你把修改
keySort状态的逻辑写在了sort的比较回调函数中,sort方法的比较回调会在排序过程中执行多次,会导致排序方向被反复翻转,最终排序逻辑完全混乱。 - 优化点:字符串类型的字段(title、body)直接用
>/<比较是按Unicode码点逐位比对,部分场景下排序结果不符合预期,建议用字符串的localeCompare方法实现。
修复后的完整代码
import React, {useEffect, useState} from 'react'; import axios from 'axios'; const url = 'https://jsonplaceholder.typicode.com/posts'; const Sort = () => { const [posts, setPosts] = useState([]); // 用useState存储排序状态,避免组件重渲染时被重置 const [sortState, setSortState] = useState({ id: 0, title: 0, body: 0 }); useEffect(() => { async function fetchData() { const data = await axios.get(url); if(data.status !== 200) console.error(data.statusText); else { setPosts(data.data); } } fetchData(); }, []); const handleHeaderClick = (event) => { const sortKey = event.target.id; // 先确定本次排序的方向,提前更新排序状态,不在sort回调中修改 const currentDir = sortState[sortKey]; const nextDir = currentDir >= 0 ? -1 : 0; setSortState(prev => ({ ...prev, [sortKey]: nextDir })); // 执行排序逻辑 setPosts(currPosts => { return [...currPosts].sort((a, b) => { if (typeof a[sortKey] === 'string') { // 字符串类型用localeCompare排序结果更符合常规预期 return currentDir >= 0 ? a[sortKey].localeCompare(b[sortKey]) : b[sortKey].localeCompare(a[sortKey]); } // 数字类型直接比较 if (a[sortKey] > b[sortKey]) return currentDir >= 0 ? 1 : -1; if (a[sortKey] < b[sortKey]) return currentDir >= 0 ? -1 : 1; return 0; }) }) } return ( <> <p>Sort Page</p> <table style={{border: '1px solid'}}> <thead> <tr> <th id="id" onClick={handleHeaderClick}>id</th> <th id="title" onClick={handleHeaderClick}>Title</th> <th id="body" onClick={handleHeaderClick}>Body</th> </tr> </thead> <tbody> {posts.map((obj, index) => { return ( <tr key={index}> <td>{obj.id}</td> <td>{obj.title}</td> <td>{obj.body}</td> </tr> ) })} </tbody> </table> </> ); } export default Sort;
内容的提问来源于stack exchange,提问作者myTest532 myTest532
相关产品推荐
相关产品推荐

