reactjs - 如何停止共享 react-table v7 useTable 状态?
问题描述
我有一个组件可以创建一个反应表,当只涉及一个页面时,它可以按预期工作:
const ReactTable = (props) => {
const {data, columns, viewState, updateViewState} = props;
const defaultColumn = React.useMemo(() => ({
Filter: DefaultColumnFilter,
updateFiltering: (column, newValue) => updateFiltering(viewState, updateViewState, column, newValue),
filter: 'standard',
canResize: true}),[]);
const {filters, filterable, groupBy, expanded, page} = viewState;
const tableInstance = useTable(
{
columns,
data,
defaultColumn,
autoResetExpanded: false,
groupByFn: (rows, columnId) => {
const getKey = value => value.label ? value.label: value;
return rows.reduce((prev, row) => {
const resKey = `${getKey(row.values[columnId])}`;
prev[resKey] = Array.isArray(prev[resKey]) ? prev[resKey] : [];
prev[resKey].push(row);
return prev}, {})},
filterTypes: {'standard': applyFilter},
pageSize: page.size,
initialState: {filters, groupBy, expanded, pageIndex: page.index}},
useFilters,
useGroupBy,
useExpanded,
usePagination,
useRowSelect,
addSelectColumn);
const {getTableProps, getTableBodyProps, setGroupBy} = tableInstance;
React.useEffect(
() => updateViewStateFromTable(viewState, tableInstance, updateViewState));
if (!isEqual(groupBy, tableInstance.state.groupBy)) setGroupBy(groupBy);
const headerRows = getHeaderRows(tableInstance, viewState, updateViewState);
const dataRows = getDataRows(tableInstance);
const filterRow = getFilterRow(tableInstance, viewState);
console.log('ReactTable', {props, tableInstance})
return (
<div>
<table className="ReactTable -highlight rt-table"
{...getTableProps()}>
<thead className="rt-thead -header">
{headerRows}
</thead>
<tbody className="rt-tbody" {...getTableBodyProps()}>
{(filterable)? filterRow:null}
{dataRows}
</tbody>
<PaginationFoot {...{viewState, tableInstance}} />
</table>
<h2>viewState:</h2>
<pre>
<code>
{JSON.stringify({viewState}, null, 4)}
</code>
</pre>
</div>)};
export default ReactTable;
不幸的是,如果我更改一页上的页面索引或大小,它也会影响所有其他页面。
“viewState”是我的构造,用于跟踪和保持过滤器、分页、扩展、列选择、分组和排序(并允许用户创建自己的自定义命名视图状态)。
似乎表的内部状态正在被破坏性修改,因为 viewState 副本显示了正确的分页数据(但在渲染后更新为不正确的共享值)。
我尝试使用 useControlledState 直接进入/退出 viewState 但这会导致错误,因为它试图在渲染操作期间更新状态。
解决方案
由于表状态是一种状态,因此该行为在技术上是正确的。这里的麻烦在于,当数据和viewState发生变化时,我想有效地重新挂载react table组件(或者重新初始化它的状态)。
有一个带有组件的“表格页面”,其属性正在发生变化,因此提供了不同的表格规范和数据内容。
路由将每个 /table/:tableName 路由到同一个 TablePage ,后者为其 ReactTable 组件提供数据和 viewState。因此 useTable 内部状态被重新用于每个表,这会导致问题。
一个详细的解决方法只是为每个表页面添加一个组件(而不仅仅是更改数据),从而改变我的路由表:
const routeMap = [
{path: '/', component: Dashboard, allowAny},
{path: '/login', component: LoginOrOut, allowAny},
{path: "/table/:tableName", component: TablePage},
{path: "/tables", component: Tables},
{path: "/new/:modelType", component: RoutedModel, action: 'new'},
...
对此:
const routeMap = [
{path: '/', component: Dashboard, allowAny},
{path: '/login', component: LoginOrOut, allowAny},
...tableNames.map(tableName =>
({path: `/table/${tableName}`, component: props => <TablePage tableName={tableName} {...props} />})),
{path: "/tables", component: Tables},
{path: "/new/:modelType", component: RoutedModel, action: 'new'},
...
这感觉很笨拙,因为我正在创建一个更大的 DOM,以便组件可以保持自己的状态,但它看起来很高效。
推荐阅读
- python - 没有命令的Django后台任务
- cmake - CMake - libtiff 交叉编译
- c++ - 如何选择在 csv 文件中的输出位置
- reactjs - 为什么在[]中更改元素时useEffect不起作用
- javascript - 使用 JS 从 AWS Lambda 访问 AWS Secrets Manager 密钥
- azure-active-directory - 授予参与者对我的存储帐户的服务主体 ID 的访问权限
- angular - 登录时出现Angular e2e测试超时问题
- java - 从链中删除根 ca(签名)
- pytorch - RuntimeError:CuDNN 错误:CUDNN_STATUS_SUCCESS
- python - doctest 中的多行列表输出