reactjs - 如果初始排序完成,使用排序数组的 React useState 不会导致 SemanticUI 表的重新渲染
问题描述
我有一个带有 SemanticUI 的表,它呈现公司列表,并允许根据单击表的标题来重新选择列表。我以为我已经完成了这项工作(开发环境正在向我发送一个预先排序的列表),但是在编写测试时,我意识到我不能保证该列表是预先排序的。
所以我编辑了我的初始useState
逻辑以具有一个排序功能,该功能与标题点击的逻辑相同:
之前(工作):
const [data, setData] = useState(companies);
之后(不起作用):
const [data, setData] = useState(companySortData(companies, COLUMN_NAME.NAME));
上面的初始 UI 看起来都不错,但是当我单击标题时,问题就出现了:UI 没有改变(重新渲染)。
在我逐步执行代码时,我看到正确的 RE-sorted 数组在那里,但是在 React 内部的某个地方,该数组不会触发状态更改。
我尝试了很多选项,包括:1)更改状态,使其data
成为. 3)尝试创建一个钩子来比较,然后在依赖项发生变化时调用。4) 从 Functional 更改为 PureComponent,但这也没有完全解决它。sortedColumnData
useEffect
setData
usePrevious
sortedColumnData
setData
我知道 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>
);
};
我不确定为什么使用重新排序的数组从设置状态重新渲染失败...
解决方案
发生这种情况是因为您将 props 的引用传递给 sort 函数并尝试将其设置为状态,您不能改变 props,这是 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;
});
};
推荐阅读
- azure-devops-rest-api - azure-devops-node-api:如何在 ProjectCollection 范围内设置DocumentByName
- css - 为 iphone 调整图像大小
- javascript - React JS 期望一个赋值或函数调用,而是看到一个表达式
- python - 安装 Adafruit 软件后 SPI 总线不工作
- java - 我的应用程序在 Android Studio 上的 Android Emulator 上启动后立即崩溃
- flutter - 如何在 Flutter 中更改 Drawer 的整个背景颜色
- php - ACF - 在页面上显示特定数据而无需对 php 进行硬编码
- python - 子进程“没有这样的文件或目录”
- sql - 使用联接更新表时如何修复此 SQL 错误?
- css - 如何在响应式设计中定位圆圈并使它们保持相同的排列?