如何在 Modal Chakra-UI 的表格中使用来自 React-Table 的 useSortBy?

How can i use useSortBy from React-Table in Table from Modal Chakra-UI?

提问人:Ken Arya 提问时间:11/16/2023 更新时间:11/16/2023 访问量:20

问:

我的项目使用带有 Chakra-UI 和 React-Table 的 Vite+React,我前面有表格,点击 textname 会弹出带有另一个表格的模态,我也想在该表格中使用 useSortBy,但如果我为该表格创建相同的变量是错误的

“未捕获的错误:超出最大更新深度。当组件在 componentWillUpdate 或 componentDidUpdate 中重复调用 setState 时,可能会发生这种情况。React 限制了嵌套更新的数量,以防止无限循环。

组件表的干净代码

import {
  Flex,
  Table,
  Tbody,
  Td,
  Text,
  Th,
  Thead,
  Tr,
  Button,
  Modal,
  ModalOverlay,
  ModalContent,
  ModalHeader,
  ModalBody,
  ModalCloseButton,
  CircularProgress,
} from '@chakra-ui/react';
import React, { useMemo, useState } from 'react';
import {
  useGlobalFilter,
  usePagination,
  useSortBy,
  useTable,
} from 'react-table';

export default function TableExample(props) {
  const { columnsData, tableData } = props;

  const columns = useMemo(() => columnsData, [columnsData]);
  const data = useMemo(() => tableData, [tableData]);

  const [isModalOpen, setIsModalOpen] = useState(false);
  const [selectedRowData, setSelectedRowData] = useState(null);

  const openModal = (rowData) => {
    setSelectedRowData(rowData);
    setIsModalOpen(true);
  };

  const tableInstance = useTable(
    {
      columns,
      data,
    },
    useGlobalFilter,
    useSortBy,
    usePagination
  );

  const {
    getTableProps,
    getTableBodyProps,
    headerGroups,
    page,
    prepareRow,
    initialState,
  } = tableInstance;
  initialState.pageSize = 10;

  return (
    <Flex direction="column">
      {tableData.length > 0 ? (
        <Flex>
          <Table
            {...getTableProps()}
            variant="striped"
            color="gray.500"
            mb="24px"
            h="100%"
            w="100%"
          >
            <Thead>
              {headerGroups.map((headerGroup, index) => (
                <Tr {...headerGroup.getHeaderGroupProps()} key={index}>
                  {headerGroup.headers.map((column, index) => (
                    <Th
                      {...column.getHeaderProps(column.getSortByToggleProps())}
                      pe="10px"
                      key={index}
                      borderColor="gray.200"
                    >
                      <Flex
                        justify="space-between"
                        align="center"
                        fontSize={{ sm: '10px', lg: '12px' }}
                        color="black"
                      >
                        {column.render('Header')}
                      </Flex>
                    </Th>
                  ))}
                </Tr>
              ))}
            </Thead>
            <Tbody {...getTableBodyProps()}>
              {page.map((row, index) => {
                prepareRow(row);
                return (
                  <Tr {...row.getRowProps()} key={index}>
                    {row.cells.map((cell, index) => {
                      let data = '';
                      if (cell.column.Header === 'NAME') {
                        data = (
                          <Flex align="center">
                            <Button
                              variant="link"
                              color={'#212529'}
                              fontSize="md"
                              fontWeight="500"
                              onClick={() => openModal(row.original)}
                            >
                              {cell.value}
                            </Button>
                          </Flex>
                        );
                      } else if (cell.column.Header === 'VALUE') {
                        data = (
                          <Text
                            color={'#212529'}
                            fontSize="sm"
                            fontWeight="500"
                          >
                            {cell.value.toLocaleString('en-EN', {
                              style: 'currency',
                              currency: 'USD',
                            })}
                          </Text>
                        );
                      }
                      return (
                        <Td
                          {...cell.getCellProps()}
                          key={index}
                          fontSize={{ sm: '14px' }}
                          maxH="30px !important"
                          py="8px"
                          minW={{ sm: '150px', md: '200px', lg: 'auto' }}
                          borderColor="transparent"
                        >
                          {data}
                        </Td>
                      );
                    })}
                  </Tr>
                );
              })}
            </Tbody>
          </Table>
        </Flex>
      ) : (
        <Flex align="center" justify="center" h="100%">
          <CircularProgress isIndeterminate color="blue.400" size="20px" />
        </Flex>
      )}
      <Modal
        size={'xl'}
        scrollBehavior={'inside'}
        isOpen={isModalOpen}
        onClose={() => setIsModalOpen(false)}
        isCentered
        motionPreset="slideInBottom"
        blockScrollOnMount={false}
      >
        <ModalOverlay />
        <ModalContent>
          <ModalHeader>
            {selectedRowData && selectedRowData.namaProjek}
          </ModalHeader>
          <ModalCloseButton />
          <ModalBody>
            {selectedRowData && selectedRowData.dataArray ? (
              <Table
                {...getTableProps()}
                variant="striped"
                color="gray.500"
                mb="24px"
              >
                <Thead position="sticky" top={0} zIndex="docked">
                  <Tr background={'#ffffff'}>
                    <Th color={'#212529'}>Material</Th>
                    <Th color={'#212529'}>Value</Th>
                  </Tr>
                </Thead>
                <Tbody {...getTableBodyProps()}>
                  {JSON.parse(selectedRowData.dataArray).map((item, index) => (
                    <Tr key={index}>
                      <Td color={'#212529'} fontSize="sm" fontWeight="500">
                        {item.material}
                      </Td>
                      <Td
                        color={'#212529'}
                        isNumeric
                        fontSize="sm"
                        fontWeight="500"
                      >
                        {item.value.toLocaleString('en-EN', {
                          style: 'currency',
                          currency: 'USD',
                        })}
                      </Td>
                    </Tr>
                  ))}
                </Tbody>
              </Table>
            ) : (
              <p>No data available</p>
            )}
          </ModalBody>
        </ModalContent>
      </Modal>
    </Flex>
  );
}

和这个例子 Stackblitz

reactjs vite react-table chakra-ui

评论

0赞 juliushuck 11/16/2023
我认为您应该为模态表分离useTable的实例。这意味着您应该在模式中再次调用 useTable、useSortBy 和其他相关钩子,以创建一个完全独立的表实例。两个表的状态和生命周期应该是独立的。
0赞 Ken Arya 11/16/2023
我会做的,谢谢你的帮助

答: 暂无答案