如何在特定列中选择一行而不触发React Table中整个行的onClick函数

问题描述

我已经设置了我的React Table,当用户单击一行时,它们将被带到另一个页面,但是现在我在第一列中添加一个复选框,允许用户突出显示该行,但是当我单击该复选框,因为它将触发单击整个行时调用函数,因此将用户带到另一个页面

我尝试获取列访问器名称,如果单击的列是第一个,则不要将用户路由到另一个页面,但是我在获取有关所选列的信息方面遇到了麻烦。我花了很多时间看文档,但无法弄清楚。

我真的很感激任何帮助,因为我通常难以掌握React Table

RecordTable.js

    import React from "react";
import {
  useTable,useFlexLayout,useFilters,useGlobalFilter,useRowSelect
} from "react-table";
import _ from "lodash";
// noinspection ES6CheckImport
import { useHistory } from "react-router-dom";
import Table from "react-bootstrap/Table";

// Define a default UI for filtering
function GlobalFilter({
  preGlobalFilteredRows,globalFilter,setGlobalFilter
}) {
  return (
    <span>
      <input
        value={globalFilter || ""}
        onChange={e => {
          setGlobalFilter(e.target.value || undefined); // Set undefined to remove the filter entirely
        }}
        placeholder={" Search by any criteria"}
        style={{
          fontSize: "2.0rem",width: "100%"
        }}
      />
    </span>
  );
}

const IndeterminateCheckBox = React.forwardRef(
  ({ indeterminate,...rest },ref) => {
    const defaultRef = React.useRef();
    const resolvedRef = ref || defaultRef;

    React.useEffect(() => {
      resolvedRef.current.indeterminate = indeterminate;
    },[resolvedRef,indeterminate]);

    return (
      <>
        <input type="checkBox" ref={resolvedRef} {...rest} />
      </>
    );
  }
);

export const RecordTable = ({ forms }) => {
  //Todo figure out why react-table crashes if forms is not set to data variable below first
  const data = forms;
  let history = useHistory();

 

  const columns = React.useMemo(
    () => [
      {
        Header: "disclaimer Form Records",columns: [
          {
            Header: "First Name",{
            Header: "Time In",accessor: "timeIn"
          },{
            Header: "Time Out",accessor: "timeOut"
          },{
            Header: "€ Price",accessor: "totalGroupPrice",disableFilters: true,disableSortBy: true
          }
        ]
      }
    ],[]
  );

  const defaultColumn = React.useMemo(
    () => ({
      //minWidth: 20,maxWidth: 150,width: 120
    }),[]
  );

  const rowOnClick = (rowObject,column) => {
    console.log("rowObject.original: ",rowObject.original);
    console.log("column.id: ",column);
    history.push("/viewform",{ ...rowObject.original });
  };



  // Use the state and functions returned from useTable to build your UI
  const {
    getTableProps,getTableBodyProps,headerGroups,rows,prepareRow,state,preGlobalFilteredRows,setGlobalFilter,setHiddenColumns,} = useTable(
    {
      columns,data,defaultColumn
    },useRowSelect,hooks => {
      hooks.visibleColumns.push(columns => [
        // Let's make a column for selection
        {
          accessor: "active",Header: "Active",width: 50,maxWidth: 50,minWidth: 50,Cell: ({ row }) => (
            <div>
              <IndeterminateCheckBox {...row.getToggleRowSelectedProps()} />
            </div>
          )
        },...columns
      ]);
    }
  );

 

  // Render the UI for your table
  return (
    <div>
      <div>Records: {rows.length}</div>
      <GlobalFilter
        preGlobalFilteredRows={preGlobalFilteredRows}
        globalFilter={state.globalFilter}
        setGlobalFilter={setGlobalFilter}
      />

      <div
        style={{
          height: 500,border: "2px solid grey",borderRadius: "5px",overflow: "scroll"
        }}>
        <Table striped bordered hover responsive={"md"} {...getTableProps()}>
          <thead>
            {headerGroups.map(headerGroup => (
              <tr {...headerGroup.getHeaderGroupProps()}>
                {headerGroup.headers.map(column => (
                  <th {...column.getHeaderProps()}>
                    {column.render("Header")}
                  </th>
                ))}
              </tr>
            ))}
          </thead>

          <tbody {...getTableBodyProps()}>
            {rows.map((row,column,i) => {
              prepareRow(row);
              return (
                <tr
                  {...row.getRowProps({
                    onClick: () => rowOnClick(row,column)
                  })}>
                  {row.cells.map(cell => {
                    return (
                      <td {...cell.getCellProps()}>{cell.render("Cell")}</td>
                    );
                  })}
                </tr>
              );
            })}
          </tbody>
        </Table>
      </div>
    </div>
  );
};

解决方法

您需要在复选框上设置onClick={e => e.stopPropagation()}

技术上,点击发生在多个元素上。复选框,单元格行等。

在JS中,事件是在顶部元素上创建的,然后通过位于鼠标指针下方的所有DOM元素传播(“冒泡”)。事件会通过不同的层冒泡,所有元素都可能对此做出反应。但是您确实想阻止它冒泡。