如何在 react-table 中将数据从行传递到对话框组件?

How can I pass data from row to dialog component in react-table?

这是我第一次使用 react-table,因为我决定在我的应用程序中重新设计一个组件。我快到了,但我发现自己在尝试将一些数据传递到单击按钮时弹出的对话框时卡住了。

在我之前的 table 设计中,使用 MUI Table,我使用 array.map() 来呈现每个行条目。然后,我需要做的就是使用 props 将数据传递给 Dialog 组件,这样每个操作按钮都会从各自的条目中加载数据(包括未显示的数据,例如 _id ).现在有了 react-table 由于逻辑改变,我不知道如何获得相同的结果。编辑和删除按钮在那里,它们触发对话框打开,但我的进度到此为止。

Entries.jsx

function Entries(props) {
  const navigate = useNavigate();

  const [openEdit, setOpenEdit] = useState(false);
  const [openDelete, setOpenDelete] = useState(false);

  const handleEdit = () => {
    setOpenEdit(true);
  };

  const handleDelete = () => {
    setOpenDelete(true);
  };

  const handleClose = () => {
    setOpenEdit(false);
    setOpenDelete(false);
  };

  const data = props.data;

  const columns = useMemo(
    () => [
      {
        Header: "#",
        id: "row",
        Cell: ({ row }) => {
          return <div>{row.index + 1}</div>;
        },
      },
      {
        Header: "Title",
        accessor: "title",
        className: "column-left",
        Cell: ({ cell: { value }, row: { original } }) => (
          <Link
            sx={{
              fontSize: "14px",
              fontWeight: 500,
              "&:hover": { color: "#00D67E" },
            }}
            color="#fff"
            underline="none"
            style={{ cursor: "pointer" }}
            onClick={() => navigate(`/details/${original.movieId}`)}
          >
            {value}
          </Link>
        ),
      },
      {
        Header: "Year",
        accessor: "year",
        className: "column-right",
      },
      {
        Header: "Rating",
        accessor: "details[0].rating",
        className: "column-right",
        Cell: ({ cell: { value } }) => (
          <Rating
            size="small"
            value={value}
            readOnly
            emptyIcon={<StarIcon fontSize="inherit" />}
          />
        ),
      },
      {
        Header: "Watched",
        accessor: "date",
        className: "column-right",
        Cell: ({ cell: { value } }) => format(new Date(value), "MMM dd, yyyy"),
      },
      {
        Header: "View Count",
        accessor: "details[0].view_count",
        className: "column-right",
      },
      {
        Header: "Review",
        accessor: "details[0].review",
        className: "column-right",
        Cell: ({ cell: { value } }) =>
          !value ? null : <CheckIcon color="primary" />,
      },
      {
        Header: "Actions",
        className: "column-right",
        Cell: () => (
          <div>
            <IconButton
              aria-label="edit"
              style={{ color: "#e0e0e0" }}
              onClick={handleEdit}
            >
              <EditIcon fontSize="small" />
            </IconButton>

            <IconButton
              aria-label="delete"
              style={{ color: "#e0e0e0", paddingRight: 0 }}
              onClick={handleDelete}
            >
              <DeleteIcon fontSize="small" />
            </IconButton>
          </div>
        ),
      },
    ],
    []
  );

  return (
    <div>
      {/* TABLE */}
      <CustomTable columns={columns} data={data} />

      {/* DIALOGS */}
      <EditDialog
        isOpen={openEdit}
        onClose={handleClose}
        id={data._id}
        movieId={data.movieId}
        date={data.date}
        rating={data.details[0].rating}
        review={data.details[0].review}
        onUpdate={props.onUpdate}
      />

      <DeleteDialog
        isOpen={openDelete}
        onClose={handleClose}
        title="Delete this entry?"
        message={
          <span>
            <strong>
              {data.title} ({data.date})
            </strong>{" "}
            will be removed. This action cannot be undone.
          </span>
        }
        onRemove={() => {
          props.onRemove(data._id, data.movieId);
        }}
      />
    </div>
  );
}

export default Entries;

后来我什至尝试了一些东西来模仿我以前设计的逻辑,因为映射是由我的 CustomTable.jsx 组件中的 rows.map((row) => { prepareRow(row) } 处理的。然后我想到了这个:

{
        Header: "Actions",
        className: "column-right",
        Cell: () => (
          <div>
            <IconButton
              aria-label="edit"
              style={{ color: "#e0e0e0" }}
              onClick={({row}) => {
                handleEdit();

                return (
                  <EditDialog
                    isOpen={openEdit}
                    onClose={handleClose}
                    id={row._id}
                    movieId={row.movieId}
                    date={row.date}
                    rating={row.details[0].rating}
                    review={row.details[0].review}
                    onUpdate={props.onUpdate}
                  />
                );
              }}
            >
              <EditIcon fontSize="small" />
            </IconButton>

            <IconButton
              aria-label="delete"
              style={{ color: "#e0e0e0", paddingRight: 0 }}
              onClick={handleDelete}
            >
              <DeleteIcon fontSize="small" />
            </IconButton>
          </div>
        ),
      }

但是也没用。它在第一个 prop 处停止并抛出一个错误,说它无法读取属性 row._id。那是我的最后一枪。

很简单,您可以将所选行存储到状态,然后在您的编辑和删除组件中使用它。试试这个

function Entries(props) { 
  const navigate = useNavigate();
  const [openEdit, setOpenEdit] = useState(false);
  const [openDelete, setOpenDelete] = useState(false);
  const [selectedRow, setSelectedRow] = useState();

  const handleEdit = (row) => {
    setOpenEdit(true);
    setSelectedRow(row);
  };

  const handleDelete = (row) => {
    setOpenDelete(true);
    setSelectedRow(row);
  };

  const handleClose = () => {
    setOpenEdit(false);
    setOpenDelete(false);
    setSelectedRow();
  };

  const data = props.data;

  const columns = useMemo(
    () => [
      {
        Header: "#",
        id: "row",
        Cell: ({ row }) => {
          return <div>{row.index + 1}</div>;
        }
      },
      {
        Header: "Title",
        accessor: "title",
        className: "column-left",
        Cell: ({ cell: { value }, row: { original } }) => (
          <Link
            sx={{
              fontSize: "14px",
              fontWeight: 500,
              "&:hover": { color: "#00D67E" }
            }}
            color="#fff"
            underline="none"
            style={{ cursor: "pointer" }}
            onClick={() => navigate(`/details/${original.movieId}`)}
          >
            {value}
          </Link>
        )
      },
      {
        Header: "Year",
        accessor: "year",
        className: "column-right"
      },
      {
        Header: "Rating",
        accessor: "details[0].rating",
        className: "column-right",
        Cell: ({ cell: { value } }) => (
          <Rating
            size="small"
            value={value}
            readOnly
            emptyIcon={<StarIcon fontSize="inherit" />}
          />
        )
      },
      {
        Header: "Watched",
        accessor: "date",
        className: "column-right",
        Cell: ({ cell: { value } }) => format(new Date(value), "MMM dd, yyyy")
      },
      {
        Header: "View Count",
        accessor: "details[0].view_count",
        className: "column-right"
      },
      {
        Header: "Review",
        accessor: "details[0].review",
        className: "column-right",
        Cell: ({ cell: { value } }) =>
          !value ? null : <CheckIcon color="primary" />
      },
      {
        Header: "Actions",
        className: "column-right",
        Cell: ({ row }) => (
          <div>
            <IconButton
              aria-label="edit"
              style={{ color: "#e0e0e0" }}
              onClick={() => handleEdit(row.original)}
            >
              <EditIcon fontSize="small" />
            </IconButton>

            <IconButton
              aria-label="delete"
              style={{ color: "#e0e0e0", paddingRight: 0 }}
              onClick={() => handleEdit(row.original)}
            >
              <DeleteIcon fontSize="small" />
            </IconButton>
          </div>
        )
      }
    ],
    []
  );

  return (
    <div>
      {/* TABLE */}
      <CustomTable columns={columns} data={data} />

      {/* DIALOGS */}
        <EditDialog
          isOpen={openEdit}
          onClose={handleClose}
          id={selectedRow?._id}
          movieId={selectedRow?.movieId}
          date={selectedRow?.date}
          rating={selectedRow?.details[0]?.rating}
          review={selectedRow?.details[0]?.review}
          onUpdate={props.onUpdate}
        />

        <DeleteDialog
          isOpen={openDelete}
          onClose={handleClose}
          title="Delete this entry?"
          message={
            <span>
              <strong>
                {selectedRow?.title} ({selectedRow?.date})
              </strong>{" "}
              will be removed. This action cannot be undone.
            </span>
          }
          onRemove={() => {
            props.onRemove(selectedRow?._id, selectedRow?.movieId);
          }}
        />
    </div>
  );
}

export default Entries;