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>
  );
}
  1. 保留所选项目 ID 的映射,并通过 Toggle 组件切换这些值。
  2. 使用切换按钮的单独状态来过滤所选项目。
  3. 实现一行道具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>
  );
}