You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React自定义表格点击表头排序不生效、排序结果混乱问题求助

React自定义表格排序问题解决方案

问题根因

  • 最早点击表头不触发重渲染的原因:最初排序时直接修改了原posts数组,没有生成新的数组引用,React浅比较state时认为状态无变化,不会触发重渲染,你后续新增的[...currPosts]拷贝数组的操作已经解决了这个问题。
  • 后续排序混乱的核心原因1:keySort Map直接定义在组件函数体中,每次组件重渲染都会被重新初始化,上次点击设置的排序状态无法持久化存储,每次点击都会回到初始值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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 18:27:04