React Table 7 - 在 Table 加载时扩展行
React Table 7 - Expand Rows on Table Load
我正在尝试在 table 加载时自动扩展反应 table 7。如果我硬编码 tables expanded initialState 它可以工作,但我需要能够以编程方式执行它,因为加载的行数会根据其他数据选择因素而变化。
我已经设置了我的 table 以便它接受 2 个道具,expandedRows
是一个布尔值,expandedRowObj
这是一个包含每一行的索引的对象和要扩展的真值。
我正在使用 useEffect
循环数据并创建一个新对象,该对象将数据索引作为键并将 true
设置为 属性。然后我将这个对象数组作为道具传递给 tables initialState.
我可以看到使用 devTools table 上的 intitalState 被设置为:
initialState: {
expanded: [{0: true}, {1: true}, {2: true},{3: true}]
}
但是,行没有展开。
如果我不使用 useEffect
函数来设置 expandedRows 状态,而只是硬编码一个名为 expandedRows
的变量,则 table 会按预期展开。我猜 table 渲染和设置初始状态之间存在断开连接,但我不确定。
这里是演示问题的沙箱:https://codesandbox.io/s/dazzling-tdd-x4890?file=/src/App.js
对于那些不想点击链接的人,这里是所有相关代码:
TABLE
import {
useTable,
useSortBy,
useGlobalFilter,
useFilters,
useResizeColumns,
useFlexLayout,
useExpanded,
usePagination
} from "react-table";
import {
Table,
InputGroup,
FormControl,
Row,
Col,
Button
} from "react-bootstrap";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import {
faArrowDown,
faArrowUp,
faAngleDoubleLeft,
faAngleDoubleRight,
faAngleLeft,
faAngleRight
} from "@fortawesome/free-solid-svg-icons";
import GlobalFilter from "./GlobalFilter";
import ColumnFilter from "./ColumnFilter";
import "./Table.css";
import "bootstrap/dist/css/bootstrap.min.css";
const MyTable = ({
columns: userColumns,
data,
renderRowSubComponent,
rowOnClick,
rowClickHandler,
headerColor,
showPagination,
showGlobalFilter,
expandRows,
expandedRowObj
}) => {
const filterTypes = React.useMemo(
() => ({
includes: (rows, id, filterValue) => {
return rows.filter((row) => {
const rowValue = row.values[id];
return rowValue !== undefined
? String(rowValue)
.toLowerCase()
.includes(String(filterValue).toLowerCase())
: true;
});
},
startsWith: (rows, id, filterValue) => {
return rows.filter((row) => {
const rowValue = row.values[id];
return rowValue !== undefined
? String(rowValue)
.toLowerCase()
.startsWith(String(filterValue).toLowerCase())
: true;
});
}
}),
[]
);
const sortTypes = React.useMemo(
() => ({
dateSort: (a, b) => {
a = new Date(a).getTime();
b = new Date(b).getTime();
return b > a ? 1 : -1;
}
}),
[]
);
const defaultColumn = React.useMemo(
() => ({
Filter: ColumnFilter,
disableFilters: true,
minWidth: 30,
width: 150,
maxWidth: 500
}),
[]
);
const {
getTableProps,
getTableBodyProps,
headerGroups,
prepareRow,
page,
canPreviousPage,
canNextPage,
pageOptions,
pageCount,
gotoPage,
nextPage,
previousPage,
setPageSize,
setGlobalFilter,
state: { globalFilter, pageIndex, pageSize }
} = useTable(
{
columns: userColumns,
data,
initialState: {
expanded:
expandRows && expandedRowObj.hasOwnProperty(0) ? expandedRowObj : {}
},
defaultColumn,
filterTypes,
sortTypes
},
useGlobalFilter,
useFilters,
useSortBy,
useResizeColumns,
useExpanded,
usePagination,
useFlexLayout
);
return (
<React.Fragment>
<Row className="float-right">
<Col>
{showGlobalFilter ? (
<GlobalFilter filter={globalFilter} setFilter={setGlobalFilter} />
) : (
""
)}
</Col>
</Row>
<Row>
<Col>
<Table
striped
bordered
hover
size="sm"
responsive
{...getTableProps()}
>
<thead>
{headerGroups.map((headerGroup, i) => (
<React.Fragment key={headerGroup.headers.length + "_hfrag"}>
<tr {...headerGroup.getHeaderGroupProps()}>
{headerGroup.headers.map((column) => (
<th
key={column.id}
className={`p-2 table-header ${
headerColor ? "primary-" + headerColor : "primary-deq"
}`}
{...column.getHeaderProps()}
>
<span {...column.getSortByToggleProps()}>
{column.render("Header")}
{column.isSorted ? (
column.isSortedDesc ? (
<FontAwesomeIcon
className="ms-3"
icon={faArrowDown}
/>
) : (
<FontAwesomeIcon
className="ms-3"
icon={faArrowUp}
/>
)
) : (
""
)}
</span>
<div
{...column.getResizerProps()}
className="resizer"
/>
{column.canResize && (
<div
{...column.getResizerProps()}
className={`resizer ${
column.isResizing ? "isResizing" : ""
}`}
/>
)}
<div>
{column.canFilter ? column.render("Filter") : null}
</div>
</th>
))}
</tr>
</React.Fragment>
))}
</thead>
<tbody {...getTableBodyProps()}>
{page.map((row, i) => {
prepareRow(row);
return (
<React.Fragment key={i + "_frag"}>
<tr
{...row.getRowProps()}
onClick={
rowOnClick
? () => rowClickHandler(row.original)
: () => ""
}
>
{row.cells.map((cell) => {
return (
<td {...cell.getCellProps()}>
{cell.render("Cell")}
</td>
);
})}
</tr>
{row.isExpanded ? (
<tr>
<td>
<span className="subTable">
{renderRowSubComponent({ row })}
</span>
</td>
</tr>
) : null}
</React.Fragment>
);
})}
</tbody>
</Table>
{showPagination ? (
<Row className="mt-2 text-center">
<Col>
<Button
className="me-2"
size="sm"
variant="secondary"
onClick={() => gotoPage(0)}
disabled={!canPreviousPage}
>
<FontAwesomeIcon icon={faAngleDoubleLeft} />
</Button>
<Button
className="me-2"
size="sm"
variant="secondary"
onClick={() => previousPage()}
disabled={!canPreviousPage}
>
<FontAwesomeIcon icon={faAngleLeft} />
</Button>
</Col>
<Col>
<span>
Page{" "}
<strong>
{pageIndex + 1} of {pageOptions.length}
</strong>
</span>
<span>
| Go to page:{" "}
<InputGroup
size="sm"
style={{ width: "20%", display: "inline-flex" }}
>
<FormControl
type="number"
defaultValue={pageIndex + 1}
onChange={(e) => {
const page = e.target.value
? Number(e.target.value) - 1
: 0;
gotoPage(page);
}}
/>
</InputGroup>
</span>
<InputGroup
size="sm"
style={{ width: "30%", display: "inline-flex" }}
>
<FormControl
className="mt-4"
size="sm"
as="select"
value={pageSize}
onChange={(e) => {
setPageSize(Number(e.target.value));
}}
>
{[5, 10, 20, 30, 40, 50].map((pageSize) => (
<option key={pageSize} value={pageSize}>
Show {pageSize}
</option>
))}
</FormControl>
</InputGroup>
</Col>
<Col>
<Button
className="me-2"
size="sm"
variant="secondary"
onClick={() => nextPage()}
disabled={!canNextPage}
>
<FontAwesomeIcon icon={faAngleRight} />
</Button>
<Button
className="me-2"
size="sm"
variant="secondary"
onClick={() => gotoPage(pageCount - 1)}
disabled={!canNextPage}
>
<FontAwesomeIcon icon={faAngleDoubleRight} />
</Button>
</Col>
</Row>
) : (
""
)}
</Col>
</Row>
</React.Fragment>
);
};
MyTable.defaultProps = {
rowOnClick: false,
showPagination: false,
expandRows: false,
expandedRowObj: {}
};
MyTable.propTypes = {
/** Specified if pagination should show or not */
showPagination: PropTypes.bool.isRequired,
/** Specifies if there should be a row onClick action*/
rowOnClick: PropTypes.bool.isRequired,
/** OPTIONAL: The onClick Action to be taken */
rowClickHandler: PropTypes.func,
/** header color background. There are six possible choices. Refer to ReadMe file for specifics */
headerColor: PropTypes.string
};
使用 TABLE 组件
const GroupedSamplingStationTable = (props) => {
const [expandedRows, setExpandedRows] = useState();
//const expandedRows = [{ 0: true }, { 1: true }, { 2: true }, { 3: true }]; //This works
const columns = [
{
Header: () => null,
id: "expander",
width: 30,
Cell: ({ row }) => (
<span {...row.getToggleRowExpandedProps()}>
{row.isExpanded ? (
<FontAwesomeIcon className="font-icon" icon={faCaretDown} />
) : (
<FontAwesomeIcon className="font-icon" icon={faCaretRight} />
)}
</span>
)
},
{
Header: "Sample Group ID",
accessor: "groupId",
width: 75
},
{
Header: "Sample Group",
accessor: "groupName",
width: 200
}
];
const details = React.useMemo(
() => [
{
Header: "Source ID",
accessor: "sourceId",
width: 50
},
{
Header: "Source Name",
accessor: "sourceName",
width: 125
},
{
Header: "Sample Group Details",
accessor: "groupDetails",
width: 100
},
{
Header: "System",
accessor: (d) => {
return d.systemNumber + " " + d.systemName;
},
width: 200
}
],
[]
);
const subTable = React.useCallback(
({ row }) =>
row.original.groupDetails.length > 0 ? (
<MyTable
columns={details}
data={row.original.groupDetails}
headerColor="grey"
/>
) : (
"No Data"
),
[details]
);
useEffect(() => {
if (data) {
let array = [];
if (data.data.getGroupedSamplingStationBySystemId.length > 0) {
data.data.getGroupedSamplingStationBySystemId.forEach((elem, index) => {
let obj = {};
obj[index] = true;
array.push(obj);
});
} else {
let obj = {};
obj[0] = false;
}
setExpandedRows(array);
}
}, []);
return (
<>
{data.data.getGroupedSamplingStationBySystemId.length > 0 ? (
<MyTable
data={data.data.getGroupedSamplingStationBySystemId}
columns={columns}
renderRowSubComponent={subTable}
expandRows={true}
expandedRowObj={expandedRows}
/>
) : (
<span>
<em>No data was found for grouped sampling stations.</em>
</span>
)}
</>
);
};
数据示例
data = {
data: {
getGroupedSamplingStationBySystemId: [
{
systemId: 1289,
groupId: "8053",
groupName: "S28-UTAH18026UTAH18103",
groupDetails: [
{
sourceId: "WS005",
sourceName: "MT OLYMPUS SPRING ABND",
groupDetails: " ",
systemNumber: "UTAH18026",
systemName: "SALT LAKE CITY WATER SYSTEM"
},
{
sourceId: "WS001",
sourceName: "MT OLYMPUS SPRING",
groupDetails: " ",
systemNumber: "UTAH18103",
systemName: "MOUNT OLYMPUS WATERS"
}
]
},
{
systemId: 1289,
groupId: "8085",
groupName: "S29-UTAH18026UTAH18050",
groupDetails: [
{
sourceId: "WS007",
sourceName: "LOWER BOUNDARY SPRING TSFR",
groupDetails: " ",
systemNumber: "UTAH18026",
systemName: "SALT LAKE CITY WATER SYSTEM"
},
{
sourceId: "WS001",
sourceName: "LOWER BOUNDARY SPRING",
groupDetails: " ",
systemNumber: "UTAH18050",
systemName: "BOUNDARY SPRING WATER CO"
}
]
},
{
systemId: 1289,
groupId: "8193",
groupName: "S30-UTAH18026UTAH18028",
groupDetails: [
{
sourceId: "WS039",
sourceName: "RICHARDS DITCH WELL [DISCONNECTED]",
groupDetails: "IGNORE THIS ONE",
systemNumber: "UTAH18026",
systemName: "SALT LAKE CITY WATER SYSTEM"
},
{
sourceId: "WS027",
sourceName: "RICHARDS DITCH WELL (SOLD/TRANSFERRED)",
groupDetails: " ",
systemNumber: "UTAH18028",
systemName: "SANDY CITY WATER SYSTEM"
}
]
},
{
systemId: 1289,
groupId: "7956",
groupName: "S63-UTAH18026UTAH18028",
groupDetails: [
{
sourceId: "WS031",
sourceName: "7901 S HIGHLAND WELL TSFR",
groupDetails: " ",
systemNumber: "UTAH18026",
systemName: "SALT LAKE CITY WATER SYSTEM"
},
{
sourceId: "WS026",
sourceName: "LITTLE COTTONWOOD WELL",
groupDetails: " ",
systemNumber: "UTAH18028",
systemName: "SANDY CITY WATER SYSTEM"
}
]
}
]
}
};
使用记忆数组,而不是使用 useEffect 改变的状态数组,似乎工作得很好(sandbox):
const expandedRows = React.useMemo(() => {
if (data?.data) {
let arr = [{0: false}];
let d = data.data;
if (d.getGroupedSamplingStationBySystemId.length > 0) {
arr = d.getGroupedSamplingStationBySystemId.map((sid, ind) => {
return { [ind]: true };
});
}
return arr;
}
}, []);
我正在尝试在 table 加载时自动扩展反应 table 7。如果我硬编码 tables expanded initialState 它可以工作,但我需要能够以编程方式执行它,因为加载的行数会根据其他数据选择因素而变化。
我已经设置了我的 table 以便它接受 2 个道具,expandedRows
是一个布尔值,expandedRowObj
这是一个包含每一行的索引的对象和要扩展的真值。
我正在使用 useEffect
循环数据并创建一个新对象,该对象将数据索引作为键并将 true
设置为 属性。然后我将这个对象数组作为道具传递给 tables initialState.
我可以看到使用 devTools table 上的 intitalState 被设置为:
initialState: {
expanded: [{0: true}, {1: true}, {2: true},{3: true}]
}
但是,行没有展开。
如果我不使用 useEffect
函数来设置 expandedRows 状态,而只是硬编码一个名为 expandedRows
的变量,则 table 会按预期展开。我猜 table 渲染和设置初始状态之间存在断开连接,但我不确定。
这里是演示问题的沙箱:https://codesandbox.io/s/dazzling-tdd-x4890?file=/src/App.js
对于那些不想点击链接的人,这里是所有相关代码:
TABLE
import {
useTable,
useSortBy,
useGlobalFilter,
useFilters,
useResizeColumns,
useFlexLayout,
useExpanded,
usePagination
} from "react-table";
import {
Table,
InputGroup,
FormControl,
Row,
Col,
Button
} from "react-bootstrap";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import {
faArrowDown,
faArrowUp,
faAngleDoubleLeft,
faAngleDoubleRight,
faAngleLeft,
faAngleRight
} from "@fortawesome/free-solid-svg-icons";
import GlobalFilter from "./GlobalFilter";
import ColumnFilter from "./ColumnFilter";
import "./Table.css";
import "bootstrap/dist/css/bootstrap.min.css";
const MyTable = ({
columns: userColumns,
data,
renderRowSubComponent,
rowOnClick,
rowClickHandler,
headerColor,
showPagination,
showGlobalFilter,
expandRows,
expandedRowObj
}) => {
const filterTypes = React.useMemo(
() => ({
includes: (rows, id, filterValue) => {
return rows.filter((row) => {
const rowValue = row.values[id];
return rowValue !== undefined
? String(rowValue)
.toLowerCase()
.includes(String(filterValue).toLowerCase())
: true;
});
},
startsWith: (rows, id, filterValue) => {
return rows.filter((row) => {
const rowValue = row.values[id];
return rowValue !== undefined
? String(rowValue)
.toLowerCase()
.startsWith(String(filterValue).toLowerCase())
: true;
});
}
}),
[]
);
const sortTypes = React.useMemo(
() => ({
dateSort: (a, b) => {
a = new Date(a).getTime();
b = new Date(b).getTime();
return b > a ? 1 : -1;
}
}),
[]
);
const defaultColumn = React.useMemo(
() => ({
Filter: ColumnFilter,
disableFilters: true,
minWidth: 30,
width: 150,
maxWidth: 500
}),
[]
);
const {
getTableProps,
getTableBodyProps,
headerGroups,
prepareRow,
page,
canPreviousPage,
canNextPage,
pageOptions,
pageCount,
gotoPage,
nextPage,
previousPage,
setPageSize,
setGlobalFilter,
state: { globalFilter, pageIndex, pageSize }
} = useTable(
{
columns: userColumns,
data,
initialState: {
expanded:
expandRows && expandedRowObj.hasOwnProperty(0) ? expandedRowObj : {}
},
defaultColumn,
filterTypes,
sortTypes
},
useGlobalFilter,
useFilters,
useSortBy,
useResizeColumns,
useExpanded,
usePagination,
useFlexLayout
);
return (
<React.Fragment>
<Row className="float-right">
<Col>
{showGlobalFilter ? (
<GlobalFilter filter={globalFilter} setFilter={setGlobalFilter} />
) : (
""
)}
</Col>
</Row>
<Row>
<Col>
<Table
striped
bordered
hover
size="sm"
responsive
{...getTableProps()}
>
<thead>
{headerGroups.map((headerGroup, i) => (
<React.Fragment key={headerGroup.headers.length + "_hfrag"}>
<tr {...headerGroup.getHeaderGroupProps()}>
{headerGroup.headers.map((column) => (
<th
key={column.id}
className={`p-2 table-header ${
headerColor ? "primary-" + headerColor : "primary-deq"
}`}
{...column.getHeaderProps()}
>
<span {...column.getSortByToggleProps()}>
{column.render("Header")}
{column.isSorted ? (
column.isSortedDesc ? (
<FontAwesomeIcon
className="ms-3"
icon={faArrowDown}
/>
) : (
<FontAwesomeIcon
className="ms-3"
icon={faArrowUp}
/>
)
) : (
""
)}
</span>
<div
{...column.getResizerProps()}
className="resizer"
/>
{column.canResize && (
<div
{...column.getResizerProps()}
className={`resizer ${
column.isResizing ? "isResizing" : ""
}`}
/>
)}
<div>
{column.canFilter ? column.render("Filter") : null}
</div>
</th>
))}
</tr>
</React.Fragment>
))}
</thead>
<tbody {...getTableBodyProps()}>
{page.map((row, i) => {
prepareRow(row);
return (
<React.Fragment key={i + "_frag"}>
<tr
{...row.getRowProps()}
onClick={
rowOnClick
? () => rowClickHandler(row.original)
: () => ""
}
>
{row.cells.map((cell) => {
return (
<td {...cell.getCellProps()}>
{cell.render("Cell")}
</td>
);
})}
</tr>
{row.isExpanded ? (
<tr>
<td>
<span className="subTable">
{renderRowSubComponent({ row })}
</span>
</td>
</tr>
) : null}
</React.Fragment>
);
})}
</tbody>
</Table>
{showPagination ? (
<Row className="mt-2 text-center">
<Col>
<Button
className="me-2"
size="sm"
variant="secondary"
onClick={() => gotoPage(0)}
disabled={!canPreviousPage}
>
<FontAwesomeIcon icon={faAngleDoubleLeft} />
</Button>
<Button
className="me-2"
size="sm"
variant="secondary"
onClick={() => previousPage()}
disabled={!canPreviousPage}
>
<FontAwesomeIcon icon={faAngleLeft} />
</Button>
</Col>
<Col>
<span>
Page{" "}
<strong>
{pageIndex + 1} of {pageOptions.length}
</strong>
</span>
<span>
| Go to page:{" "}
<InputGroup
size="sm"
style={{ width: "20%", display: "inline-flex" }}
>
<FormControl
type="number"
defaultValue={pageIndex + 1}
onChange={(e) => {
const page = e.target.value
? Number(e.target.value) - 1
: 0;
gotoPage(page);
}}
/>
</InputGroup>
</span>
<InputGroup
size="sm"
style={{ width: "30%", display: "inline-flex" }}
>
<FormControl
className="mt-4"
size="sm"
as="select"
value={pageSize}
onChange={(e) => {
setPageSize(Number(e.target.value));
}}
>
{[5, 10, 20, 30, 40, 50].map((pageSize) => (
<option key={pageSize} value={pageSize}>
Show {pageSize}
</option>
))}
</FormControl>
</InputGroup>
</Col>
<Col>
<Button
className="me-2"
size="sm"
variant="secondary"
onClick={() => nextPage()}
disabled={!canNextPage}
>
<FontAwesomeIcon icon={faAngleRight} />
</Button>
<Button
className="me-2"
size="sm"
variant="secondary"
onClick={() => gotoPage(pageCount - 1)}
disabled={!canNextPage}
>
<FontAwesomeIcon icon={faAngleDoubleRight} />
</Button>
</Col>
</Row>
) : (
""
)}
</Col>
</Row>
</React.Fragment>
);
};
MyTable.defaultProps = {
rowOnClick: false,
showPagination: false,
expandRows: false,
expandedRowObj: {}
};
MyTable.propTypes = {
/** Specified if pagination should show or not */
showPagination: PropTypes.bool.isRequired,
/** Specifies if there should be a row onClick action*/
rowOnClick: PropTypes.bool.isRequired,
/** OPTIONAL: The onClick Action to be taken */
rowClickHandler: PropTypes.func,
/** header color background. There are six possible choices. Refer to ReadMe file for specifics */
headerColor: PropTypes.string
};
使用 TABLE 组件
const GroupedSamplingStationTable = (props) => {
const [expandedRows, setExpandedRows] = useState();
//const expandedRows = [{ 0: true }, { 1: true }, { 2: true }, { 3: true }]; //This works
const columns = [
{
Header: () => null,
id: "expander",
width: 30,
Cell: ({ row }) => (
<span {...row.getToggleRowExpandedProps()}>
{row.isExpanded ? (
<FontAwesomeIcon className="font-icon" icon={faCaretDown} />
) : (
<FontAwesomeIcon className="font-icon" icon={faCaretRight} />
)}
</span>
)
},
{
Header: "Sample Group ID",
accessor: "groupId",
width: 75
},
{
Header: "Sample Group",
accessor: "groupName",
width: 200
}
];
const details = React.useMemo(
() => [
{
Header: "Source ID",
accessor: "sourceId",
width: 50
},
{
Header: "Source Name",
accessor: "sourceName",
width: 125
},
{
Header: "Sample Group Details",
accessor: "groupDetails",
width: 100
},
{
Header: "System",
accessor: (d) => {
return d.systemNumber + " " + d.systemName;
},
width: 200
}
],
[]
);
const subTable = React.useCallback(
({ row }) =>
row.original.groupDetails.length > 0 ? (
<MyTable
columns={details}
data={row.original.groupDetails}
headerColor="grey"
/>
) : (
"No Data"
),
[details]
);
useEffect(() => {
if (data) {
let array = [];
if (data.data.getGroupedSamplingStationBySystemId.length > 0) {
data.data.getGroupedSamplingStationBySystemId.forEach((elem, index) => {
let obj = {};
obj[index] = true;
array.push(obj);
});
} else {
let obj = {};
obj[0] = false;
}
setExpandedRows(array);
}
}, []);
return (
<>
{data.data.getGroupedSamplingStationBySystemId.length > 0 ? (
<MyTable
data={data.data.getGroupedSamplingStationBySystemId}
columns={columns}
renderRowSubComponent={subTable}
expandRows={true}
expandedRowObj={expandedRows}
/>
) : (
<span>
<em>No data was found for grouped sampling stations.</em>
</span>
)}
</>
);
};
数据示例
data = {
data: {
getGroupedSamplingStationBySystemId: [
{
systemId: 1289,
groupId: "8053",
groupName: "S28-UTAH18026UTAH18103",
groupDetails: [
{
sourceId: "WS005",
sourceName: "MT OLYMPUS SPRING ABND",
groupDetails: " ",
systemNumber: "UTAH18026",
systemName: "SALT LAKE CITY WATER SYSTEM"
},
{
sourceId: "WS001",
sourceName: "MT OLYMPUS SPRING",
groupDetails: " ",
systemNumber: "UTAH18103",
systemName: "MOUNT OLYMPUS WATERS"
}
]
},
{
systemId: 1289,
groupId: "8085",
groupName: "S29-UTAH18026UTAH18050",
groupDetails: [
{
sourceId: "WS007",
sourceName: "LOWER BOUNDARY SPRING TSFR",
groupDetails: " ",
systemNumber: "UTAH18026",
systemName: "SALT LAKE CITY WATER SYSTEM"
},
{
sourceId: "WS001",
sourceName: "LOWER BOUNDARY SPRING",
groupDetails: " ",
systemNumber: "UTAH18050",
systemName: "BOUNDARY SPRING WATER CO"
}
]
},
{
systemId: 1289,
groupId: "8193",
groupName: "S30-UTAH18026UTAH18028",
groupDetails: [
{
sourceId: "WS039",
sourceName: "RICHARDS DITCH WELL [DISCONNECTED]",
groupDetails: "IGNORE THIS ONE",
systemNumber: "UTAH18026",
systemName: "SALT LAKE CITY WATER SYSTEM"
},
{
sourceId: "WS027",
sourceName: "RICHARDS DITCH WELL (SOLD/TRANSFERRED)",
groupDetails: " ",
systemNumber: "UTAH18028",
systemName: "SANDY CITY WATER SYSTEM"
}
]
},
{
systemId: 1289,
groupId: "7956",
groupName: "S63-UTAH18026UTAH18028",
groupDetails: [
{
sourceId: "WS031",
sourceName: "7901 S HIGHLAND WELL TSFR",
groupDetails: " ",
systemNumber: "UTAH18026",
systemName: "SALT LAKE CITY WATER SYSTEM"
},
{
sourceId: "WS026",
sourceName: "LITTLE COTTONWOOD WELL",
groupDetails: " ",
systemNumber: "UTAH18028",
systemName: "SANDY CITY WATER SYSTEM"
}
]
}
]
}
};
使用记忆数组,而不是使用 useEffect 改变的状态数组,似乎工作得很好(sandbox):
const expandedRows = React.useMemo(() => {
if (data?.data) {
let arr = [{0: false}];
let d = data.data;
if (d.getGroupedSamplingStationBySystemId.length > 0) {
arr = d.getGroupedSamplingStationBySystemId.map((sid, ind) => {
return { [ind]: true };
});
}
return arr;
}
}, []);