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

MUI TableCell sortDirection属性不生效 表格行位置错乱问题

问题根因

你给TableCell加的sortDirection属性完全没用,这个是MUI Table提供的排序状态标记,仅用来给表头加排序箭头样式,不会自动控制行顺序。
行移位的核心原因有两点:

  • JS对象本身不保证键的枚举顺序稳定:react-cookie更新cookie时会重构存储对象,被更新的键会被移到对象键列表的末尾,直接遍历Object.keys(cookies)拿到的顺序自然会乱。
  • 你写的key={index}是错误用法:以数组索引作为列表key,一旦遍历顺序变化,React会错误复用DOM节点,加剧渲染异常。
修复方法

不要依赖cookies对象的原生键顺序渲染,单独维护一份固定的商品顺序列表,渲染时严格按照这个列表取数,同时修正列表key的写法;另外注意不要直接修改从cookie里拿到的原对象,更新时要做浅拷贝,避免不可变数据问题。

修复后完整代码
import { useState } from 'react';
import { useCookies } from 'react-cookie';
import { Table, TableBody, TableCell, TableContainer, TableHead, TableRow, Paper, Button, ButtonGroup } from '@mui/material';

export default function CartItemsTable() {
const [cookies, setCookie, removeCookie] = useCookies();
// 维护固定的商品展示顺序,新增商品时把对应article字段存入该数组即可
const [cartItemOrder, setCartItemOrder] = useState(() => {
  // 初始化时取当前cookies里的键作为初始顺序
  return Object.keys(cookies)
})

function IncreaseQTY(article) {
  // 不直接修改原cookie对象,浅拷贝生成新对象
  const newCookie = {...cookies[article]};
  newCookie.qty++;
  setCookie(article, newCookie, {
    expires: new Date(Date.now() + 604800000),
  });
  // 新加入购物车的商品,追加到顺序列表末尾
  if (!cartItemOrder.includes(article)) {
    setCartItemOrder(prev => [...prev, article])
  }
}

function DecreaseQTY(article) {
  const newCookie = {...cookies[article]};
  newCookie.qty--;
  if (newCookie.qty === 0) {
    removeCookie(article);
    // 商品移除时同步从顺序列表中删除对应项
    setCartItemOrder(prev => prev.filter(item => item !== article))
  } else {
    setCookie(article, newCookie, {
      expires: new Date(Date.now() + 604800000),
    });
  }
}

return (
<TableContainer component={Paper}>
  <Table sx={{ minWidth: 650 }} >
    <TableHead>
      <TableRow>
        <TableCell >Name</TableCell>
        <TableCell align="center">Code</TableCell>
        <TableCell align="center">Price</TableCell>
        <TableCell align="center">QTY</TableCell>
        <TableCell align="center">Total</TableCell>
      </TableRow>
    </TableHead>
    <TableBody>
      {/* 按照本地维护的固定顺序遍历,不再直接依赖Object.keys(cookies)的返回顺序 */}
      {cartItemOrder.map(function (articleKey) {
        const item = cookies[articleKey]
        // 过滤掉已经被删除的cookie项,避免渲染空数据
        if (!item) return null
        return (
          <TableRow
            key={articleKey}
            sx={{ "&:last-child td, &:last-child th": { border: 0 } }}
          >
            <TableCell component="th" scope="row">
              {item.name}
            </TableCell>
            <TableCell align="center">{item.article}</TableCell>
            <TableCell align="center">{item.price}</TableCell>

            <TableCell align="center">
              <ButtonGroup
                variant="contained"
                aria-label="outlined primary button group"
              >
                <Button
                  onClick={() => {
                    DecreaseQTY(item.article);
                  }}
                >
                  -
                </Button>
                <Button variant="text" disableRipple={true}>
                  {item.qty}
                </Button>
                <Button
                  onClick={() => {
                    IncreaseQTY(item.article);
                  }}
                >
                  +
                </Button>
              </ButtonGroup>
            </TableCell>
            <TableCell align="center">
              {item.qty * item.price}
            </TableCell>
          </TableRow>
        );
      })}
    </TableBody>
  </Table>
</TableContainer>
);
}
改动说明
  • 移除了无效的sortDirection属性,该属性无任何自动控制排序/固定顺序的能力。
  • 所有cookie更新操作都做了对象浅拷贝,避免直接修改原state导致的隐式bug。
  • TableRow的key替换为商品唯一标识article,不会再因为顺序变化出现DOM复用错误。

内容的提问来源于stack exchange,提问作者Jeyhun085

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 08:21:31