如果完成了初始排序,带有已排序数组的useuseState不会导致SemanticUI表的重新呈现

问题描述 投票:0回答:1

我有一个带有SemanticUI的表,该表呈现公司列表,并允许通过单击表头对列表进行重新排序。我以为我已经把它整理好了(开发环境正在向我发送一个预先排序的列表),但是在编写测​​试时,我意识到我不能保证该列表是预先排序的。因此,我编辑了初始的useState逻辑以具有排序功能,该功能与标题单击的逻辑相同:

[之前(有效):const [data, setData] = useState(companies);

之后(不起作用):const [data, setData] = useState(companySortData(companies, COLUMN_NAME.NAME));

初始的UI在以上两个方面看起来都不错,但是当我单击标题时,这就是问题所在:UI不变(重新渲染)。

在我遍历代码时,我看到在那里有正确的RE排序数组,但是在React内部,该数组不会触发状态更改。

我尝试了很多选择,包括:1)更改状态,以使datasortedColumnData的一部分,2)制作一个useEffect挂钩,以允许初始公司数据存在,然后我们setData。 3)尝试创建一个比较usePrevioussortedColumnData钩子,然后在依赖关系发生变化时调用setData。 4)从Functional更改为PureComponent,但这也不能完全解决它。

我知道React仅是浅差异,因此可能是其中的一部分,但是数据数组形状本身较浅,所以我认为这将被采用(如果我不对数据进行初始排序,也是如此):

{
  id: "newnew",
  name: "A New New Company",
  subdomain: "newnew",
  createdAt: "2019-10-28T21:54:30.253Z",
  updatedAt: "2019-10-28T21:54:30.253Z"
},

所以,这是一个CodeSandBox链接:https://codesandbox.io/s/wonderful-thompson-vg2x1

这里是组件本身:

export const CompanyTable = ({ companies }) => {
  const [sortedColumnData, setSortedColumnData] = useState({
    data: companySortData(companies, COLUMN_NAME.NAME), // swap this initial sorting with just the `companies` and this table works fine
    direction: DIRECTION.ASCENDING,
    columnName: COLUMN_NAME.NAME
  });

  const handleClick = clickedColumn => {
    if (!clickedColumn) return;

    if (sortedColumnData.columnName !== clickedColumn) {
      setSortedColumnData({
        data: companySortData(sortedColumnData.data, clickedColumn),
        columnName: clickedColumn,
        direction: DIRECTION.ASCENDING
      });
      return;
    }

    setSortedColumnData({
      data: sortedColumnData.data.reverse(),
      columnName: clickedColumn,
      direction:
        sortedColumnData.direction === DIRECTION.ASCENDING
          ? DIRECTION.DESCENDING
          : DIRECTION.ASCENDING
    });
  };
  return (
    <Table celled selectable sortable>
      <Table.Header>
        <Table.Row>
          {headerCells.map(cell => (
            <Table.HeaderCell
              key={`cell-${cell.testid}`}
              sorted={
                sortedColumnData.columnName === cell.clickHandlerText
                  ? sortedColumnData.direction
                  : undefined
              }
              data-testid={`header-${cell.testid}`}
              onClick={() => handleClick(cell.clickHandlerText)}
            >
              {cell.title}
            </Table.HeaderCell>
          ))}
        </Table.Row>
      </Table.Header>
      <Table.Body data-testid="company-table-body">
        {sortedColumnData.data.map(
          ({ id, name, subdomain, createdAt, updatedAt }) => {
            return (
              <Table.Row
                key={id}
                role="link"
                data-testid={id}
                style={{ cursor: "pointer" }}
              >
                <Table.Cell singleLine>{name}</Table.Cell>
                <Table.Cell singleLine>{subdomain}</Table.Cell>
                <Table.Cell singleLine>{createdAt}</Table.Cell>
                <Table.Cell singleLine>{updatedAt}</Table.Cell>
              </Table.Row>
            );
          }
        )}
      </Table.Body>
    </Table>
  );
};

我不确定为什么从具有重新排序数组的设置状态重新渲染失败...

reactjs react-hooks
1个回答
1
投票

之所以发生,是因为您传递了props的引用以对函数进行排序并尝试将其设置为状态,因此您无法对prop进行突变,这是React的基础。如果您要将道具存储到状态中,请先杀死参考。希望它能回答您的疑问:)

  const companySortData = (data, sortBy) => {
  let copyData = JSON.parse(JSON.stringify(data));
  return copyData.sort((a, b) => {
    let x = a[sortBy];
    let y = b[sortBy];
    if (sortBy === COLUMN_NAME.CREATED || sortBy === COLUMN_NAME.UPDATED) {
      x = new Date(a.createdAt);
      y = new Date(b.createdAt);
    } else {
      x = a[sortBy].toLowerCase();
      y = b[sortBy].toLowerCase();
    }
    return x < y ? -1 : x > y ? 1 : 0;
  });
};
© www.soinside.com 2019 - 2024. All rights reserved.