小编典典

如何在 React 中选择多行和子行?

all

我正在寻找一些帮助来在我的 React 应用程序中实现行选择功能。

我有以下数据提供给表(react-data-table-component):

const data = useMemo(
  () =>
    [...Array(87)].map((_, outer) => ({
      id: `o-${outer}`,
      name: randFullName(),
      age: randNumber({ max: 100 }),
      price: randNumber({ max: 5000 }),
      description: randProductDescription(),
      active: randBoolean(),
      date: randFutureDate().toLocaleString(),
      items: [...Array(randNumber({ max: 10 }))].map((__, inner) => ({
        id: `o-${outer}--i-${inner}`,
        name: randFullName(),
        age: randNumber({ max: 100 }),
        price: randNumber({ max: 5000 }),
        description: randProductDescription(),
        active: randBoolean(),
        date: randFutureDate().toLocaleString(),
      })),
    })),
  [],
);

我在表格中显示这些数据。

有一个父行,每个父行都可以展开,其中包含子行。

在此处输入图像描述

现在,我希望能够选择行。我使用三态复选框,其中三个状态是:

  • 已检查:检查所有子行时
  • 空:当没有选择子行时
  • 中级:选择一些孩子行时

我想呈现复选框状态并且还能够访问选定的行。

我正在使用这样的自定义选择器单元格:

const SelectorCell = ({
  rowId,
  parentId,
  siblingIds,
  childrenIds,
}: {
  rowId: string;
  parentId: string;
  siblingIds: string[];
  childrenIds: string[];
}) => {
  const { toggleRow, rowSelectionStatus } = useContext(
    NewTableSelectedRowsContext,
  ) as NewTableSelectedRowsType;

  const handleToggle = useCallback(() => {
    // todo
  }, []);

  const status = rowSelectionStatus(rowId);

  return <ThreeStateCheckbox checked={status} onChange={handleToggle} />;
};

我尝试使用上下文提供程序来实现这一点,但没有取得任何成功:

import { createContext, useCallback, useMemo, useState } from "react";
import {
  NewTableSelectedRowsType,
} from "./types";

const statusTypes = {
  checked: true,
  intermediate: null,
  unchecked: false,
};

export const NewTableSelectedRowsContext = createContext<NewTableSelectedRowsType | null>(null);

interface Props {
  children: JSX.Element;
}

export const NewTableSelectedRowsContextProvider = ({ children }: Props): JSX.Element => {
  const rowSelectionStatus = useCallback((rowId: string) => // todo, []);

  const toggleRow = useCallback(() => {
      // todo
    },
    [],
  );

  const value: NewTableSelectedRowsType = useMemo(
    () => ({
      toggleRow,
      rowSelectionStatus,
    }),
    [rowSelectionStatus, toggleRow],
  );

  return (
    <NewTableSelectedRowsContext.Provider value={value}>
      {children}
    </NewTableSelectedRowsContext.Provider>
  );
};

我怎样才能在 React 中实现这一点?


阅读 69

收藏
2022-06-07

共1个答案

小编典典

我不确定您为什么要使用上下文来存储选择行的逻辑,data.length如果选择的行与表行的数量相同/绝对为 0,您将需要发送计算。您也没有t附加到组件代码,所以我的回答会更笼统......

您可以拥有表状态的状态和选定行的状态

enum ETableState {
  checked = 'checked',
  empty = 'empty',
  intermediate = 'intermediate'
}

const [tableState, setTableState] = useState<ETableState>(ETableState.intermediate)
const [selectedRows, setSelectedRows] = useState<string[])([])

在每个选择行上,您将调用回调以将其从selectedRows状态中添加/删除,之后将触发效果

const toggleRow = useCallback((id: string) =>
    setSelectedRows(prev => 
        prev.includes(id) ? prev.filter(i => i != id) : [...prev, id]
    )
 , [selectedRows.length])  

useEffect(() => {
  setTableState(data.length === selectedRows.length ?
                  ETableState.checked 
                : !data.length ?
                  ETableState.empty
                : ETableState.intermediate
 }
 ,[selectedRows.length, data.length]
2022-06-07