REACT TABLE- 隐藏 table 中的行并重置按钮以显示隐藏的行
REACT TABLE- Hide rows in table & reset button to display hidden rows
在我的专栏 Show
中有一个 switch
按钮(Toggle
似乎在沙盒中不起作用,可能是因为 tailwindcss
?但它在本地有效...) 当您点击它时,它会将所选行变成灰色(就好像该行被禁用但您仍然可以查看内容)。
我们也有可能再次切换并出现原始行(没有灰色)。
table 上方的 VisibilityIcon
按钮将从所有 table 中删除 gray/disabled 行(也不起作用)。还有一个 VisibilityoffIcon
按钮可以重置所有(我们得到原来的 table)。
这是我所做的,但是当我点击 Toggle
时出现错误,所有 table 都被隐藏了:
export default function MenuDisplay() {
const { menuId } = useParams();
const { match } = JsonRules;
const dataFindings = match.find((el) => el._id_menu === menuId)?._ids ?? [];
const [disabled, setDisabled] = useState(false);
const toggler_disabled = () => {
disabled ? setDisabled(false) : setDisabled(true);
};
const data = useMemo(
() => [
//some headers ....
{
Header: 'Show',
accessor: (row) =>
<Toggle onClick ={toggler_disabled} value={disabled} onChange=
{setDisabled} />
}
],[]
);
...
return (
{
disabled?
<Table
data = { dataFindings }
columns = { data }
/>
: null
}
);
}
您在行数据下使用 useMemo
,它会记住所有具有相同点击事件但没有依赖关系的行。如果你想用更新后的状态调用useMemo
,你可以这样实现
//`show` is your state
//`data` is your rows
useMemo(() => data, [show])
第二个问题是您跟踪 show
状态,它只是一个 true/false 值。如果你想有多个行状态,你需要把它作为一个数组来保存。
这是完整的代码和一些解释(您也可以查看 this playground)
import Table from "./Table";
import React, { useState, useMemo } from "react";
import JsonData from "./match.json";
import { useParams } from "react-router-dom";
import { Link } from "react-router-dom";
import VisibilityOffIcon from "@mui/icons-material/VisibilityOff";
import VisibilityIcon from "@mui/icons-material/Visibility";
export default function MenuDisplay() {
const { menuId } = useParams();
const { match } = JsonData;
const [hiddenRows, setHiddenRows] = useState([]);
const matchData = match.find((el) => el._id_menu === menuId)?._ids ?? [];
//update hidden row list
const updateHiddenRows = (rowId) => {
if (hiddenRows.includes(rowId)) {
//remove the current clicked row from the hidden row list
setHiddenRows(hiddenRows.filter((row) => row !== rowId));
} else {
//add the current clicked row from the hidden row list
setHiddenRows([...hiddenRows, rowId]);
}
};
const data = useMemo(() => [
{
Header: "Name",
accessor: (row) =>
//check current row is in hidden rows or not
!hiddenRows.includes(row._id) && (
<Link to={{ pathname: `/menu/${menuId}/${row._id}` }}>
{row.name}
</Link>
)
},
{
Header: "Description",
//check current row is in hidden rows or not
accessor: (row) => !hiddenRows.includes(row._id) && row.description
},
{
Header: "Dishes",
//check current row is in hidden rows or not
accessor: (row) => !hiddenRows.includes(row._id) && row.dishes,
Cell: ({ value }) => value && Object.values(value[0]).join(", ")
},
{
Header: "Show",
accessor: (row) => (
<button onClick={() => updateHiddenRows(row._id)}>
{!hiddenRows.includes(row._id) ? (
<VisibilityIcon>Show</VisibilityIcon>
) : (
<VisibilityOffIcon>Show</VisibilityOffIcon>
)}
</button>
)
}
], [hiddenRows]);
const initialState = {
sortBy: [
{ desc: false, id: "id" },
{ desc: false, id: "description" },
{ desc: false, id: "dishes" }
]
};
return (
<div>
<Table
data={matchData}
columns={data}
initialState={initialState}
withCellBorder
withRowBorder
withSorting
withPagination
/>
</div>
);
}
- 保留所选项目 ID 的映射,并通过
Toggle
组件切换这些值。
- 使用切换按钮的单独状态来过滤所选项目。
- 实现一行道具getter。
示例:
菜单显示
function MenuDisplay() {
const { menuId } = useParams();
const { match } = JsonData;
// toggle show/hide button
const [hideSelected, setHideSelected] = useState(false);
// select rows by item id
const [selected, setSelected] = useState({});
const rowSelectHandler = (id) => (checked) => {
setSelected((selected) => ({
...selected,
[id]: checked
}));
};
const toggleShow = () => setHideSelected((hide) => !hide);
const matchData = (
match.find((el) => el._id_menu === menuId)?._ids ?? []
).filter(({ _id }) => {
if (hideSelected) {
return !selected[_id];
}
return true;
});
const getRowProps = (row) => {
return {
style: {
backgroundColor: selected[row.values.id] ? "lightgrey" : "white"
}
};
};
const data = [
{
// add item id to row data
Header: "id",
accessor: (row) => row._id
},
{
Header: "Name",
accessor: (row) => (
<Link to={{ pathname: `/menu/${menuId}/${row._id}` }}>{row.name}</Link>
)
},
{
Header: "Description",
accessor: (row) => row.description
},
{
Header: "Dishes",
accessor: (row) => row.dishes,
id: "dishes",
Cell: ({ value }) => value && Object.values(value[0]).join(", ")
},
{
Header: "Show",
accessor: (row) => (
<Toggle
value={selected[row._id]}
onChange={rowSelectHandler(row._id)}
/>
)
}
];
const initialState = {
sortBy: [
{ desc: false, id: "id" },
{ desc: false, id: "description" }
],
hiddenColumns: ["dishes", "id"] // <-- hide id column too
};
return (
<div>
<button type="button" onClick={toggleShow}>
{hideSelected ? <VisibilityOffIcon /> : <VisibilityIcon />}
</button>
<Table
data={matchData}
columns={data}
initialState={initialState}
withCellBorder
withRowBorder
withSorting
withPagination
rowProps={getRowProps} // <-- pass rowProps getter
/>
</div>
);
}
Table
export default function Table({
className,
data,
columns,
initialState,
withCellBorder,
withRowBorder,
withSorting,
withPagination,
withColumnSelect,
rowProps = () => ({}) // <-- destructure row props getter
}) {
...
return (
<div className={className}>
...
<div className="....">
<table className="w-full" {...getTableProps()}>
<thead className="....">
...
</thead>
<tbody {...getTableBodyProps()}>
{(withPagination ? page : rows).map((row) => {
prepareRow(row);
return (
<tr
className={....}
{...row.getRowProps(rowProps(row))} // <-- call row props getter
>
...
</tr>
);
})}
</tbody>
</table>
</div>
</div>
);
}
在我的专栏 Show
中有一个 switch
按钮(Toggle
似乎在沙盒中不起作用,可能是因为 tailwindcss
?但它在本地有效...) 当您点击它时,它会将所选行变成灰色(就好像该行被禁用但您仍然可以查看内容)。
我们也有可能再次切换并出现原始行(没有灰色)。
table 上方的 VisibilityIcon
按钮将从所有 table 中删除 gray/disabled 行(也不起作用)。还有一个 VisibilityoffIcon
按钮可以重置所有(我们得到原来的 table)。
这是我所做的,但是当我点击 Toggle
时出现错误,所有 table 都被隐藏了:
export default function MenuDisplay() {
const { menuId } = useParams();
const { match } = JsonRules;
const dataFindings = match.find((el) => el._id_menu === menuId)?._ids ?? [];
const [disabled, setDisabled] = useState(false);
const toggler_disabled = () => {
disabled ? setDisabled(false) : setDisabled(true);
};
const data = useMemo(
() => [
//some headers ....
{
Header: 'Show',
accessor: (row) =>
<Toggle onClick ={toggler_disabled} value={disabled} onChange=
{setDisabled} />
}
],[]
);
...
return (
{
disabled?
<Table
data = { dataFindings }
columns = { data }
/>
: null
}
);
}
您在行数据下使用 useMemo
,它会记住所有具有相同点击事件但没有依赖关系的行。如果你想用更新后的状态调用useMemo
,你可以这样实现
//`show` is your state
//`data` is your rows
useMemo(() => data, [show])
第二个问题是您跟踪 show
状态,它只是一个 true/false 值。如果你想有多个行状态,你需要把它作为一个数组来保存。
这是完整的代码和一些解释(您也可以查看 this playground)
import Table from "./Table";
import React, { useState, useMemo } from "react";
import JsonData from "./match.json";
import { useParams } from "react-router-dom";
import { Link } from "react-router-dom";
import VisibilityOffIcon from "@mui/icons-material/VisibilityOff";
import VisibilityIcon from "@mui/icons-material/Visibility";
export default function MenuDisplay() {
const { menuId } = useParams();
const { match } = JsonData;
const [hiddenRows, setHiddenRows] = useState([]);
const matchData = match.find((el) => el._id_menu === menuId)?._ids ?? [];
//update hidden row list
const updateHiddenRows = (rowId) => {
if (hiddenRows.includes(rowId)) {
//remove the current clicked row from the hidden row list
setHiddenRows(hiddenRows.filter((row) => row !== rowId));
} else {
//add the current clicked row from the hidden row list
setHiddenRows([...hiddenRows, rowId]);
}
};
const data = useMemo(() => [
{
Header: "Name",
accessor: (row) =>
//check current row is in hidden rows or not
!hiddenRows.includes(row._id) && (
<Link to={{ pathname: `/menu/${menuId}/${row._id}` }}>
{row.name}
</Link>
)
},
{
Header: "Description",
//check current row is in hidden rows or not
accessor: (row) => !hiddenRows.includes(row._id) && row.description
},
{
Header: "Dishes",
//check current row is in hidden rows or not
accessor: (row) => !hiddenRows.includes(row._id) && row.dishes,
Cell: ({ value }) => value && Object.values(value[0]).join(", ")
},
{
Header: "Show",
accessor: (row) => (
<button onClick={() => updateHiddenRows(row._id)}>
{!hiddenRows.includes(row._id) ? (
<VisibilityIcon>Show</VisibilityIcon>
) : (
<VisibilityOffIcon>Show</VisibilityOffIcon>
)}
</button>
)
}
], [hiddenRows]);
const initialState = {
sortBy: [
{ desc: false, id: "id" },
{ desc: false, id: "description" },
{ desc: false, id: "dishes" }
]
};
return (
<div>
<Table
data={matchData}
columns={data}
initialState={initialState}
withCellBorder
withRowBorder
withSorting
withPagination
/>
</div>
);
}
- 保留所选项目 ID 的映射,并通过
Toggle
组件切换这些值。 - 使用切换按钮的单独状态来过滤所选项目。
- 实现一行道具getter。
示例:
菜单显示
function MenuDisplay() {
const { menuId } = useParams();
const { match } = JsonData;
// toggle show/hide button
const [hideSelected, setHideSelected] = useState(false);
// select rows by item id
const [selected, setSelected] = useState({});
const rowSelectHandler = (id) => (checked) => {
setSelected((selected) => ({
...selected,
[id]: checked
}));
};
const toggleShow = () => setHideSelected((hide) => !hide);
const matchData = (
match.find((el) => el._id_menu === menuId)?._ids ?? []
).filter(({ _id }) => {
if (hideSelected) {
return !selected[_id];
}
return true;
});
const getRowProps = (row) => {
return {
style: {
backgroundColor: selected[row.values.id] ? "lightgrey" : "white"
}
};
};
const data = [
{
// add item id to row data
Header: "id",
accessor: (row) => row._id
},
{
Header: "Name",
accessor: (row) => (
<Link to={{ pathname: `/menu/${menuId}/${row._id}` }}>{row.name}</Link>
)
},
{
Header: "Description",
accessor: (row) => row.description
},
{
Header: "Dishes",
accessor: (row) => row.dishes,
id: "dishes",
Cell: ({ value }) => value && Object.values(value[0]).join(", ")
},
{
Header: "Show",
accessor: (row) => (
<Toggle
value={selected[row._id]}
onChange={rowSelectHandler(row._id)}
/>
)
}
];
const initialState = {
sortBy: [
{ desc: false, id: "id" },
{ desc: false, id: "description" }
],
hiddenColumns: ["dishes", "id"] // <-- hide id column too
};
return (
<div>
<button type="button" onClick={toggleShow}>
{hideSelected ? <VisibilityOffIcon /> : <VisibilityIcon />}
</button>
<Table
data={matchData}
columns={data}
initialState={initialState}
withCellBorder
withRowBorder
withSorting
withPagination
rowProps={getRowProps} // <-- pass rowProps getter
/>
</div>
);
}
Table
export default function Table({
className,
data,
columns,
initialState,
withCellBorder,
withRowBorder,
withSorting,
withPagination,
withColumnSelect,
rowProps = () => ({}) // <-- destructure row props getter
}) {
...
return (
<div className={className}>
...
<div className="....">
<table className="w-full" {...getTableProps()}>
<thead className="....">
...
</thead>
<tbody {...getTableBodyProps()}>
{(withPagination ? page : rows).map((row) => {
prepareRow(row);
return (
<tr
className={....}
{...row.getRowProps(rowProps(row))} // <-- call row props getter
>
...
</tr>
);
})}
</tbody>
</table>
</div>
</div>
);
}