react-grid-layout / react-resizable

A simple React component that is resizable with a handle.

Home Page:https://strml.github.io/react-resizable/examples/1.html

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Uncaught Error: <DraggableCore>: Unmounted during event!

wjyzhixing opened this issue · comments

my code is this:

import React, { useState, useEffect } from 'react';
import { Table, Tag, Button, Select } from 'antd';
import { Resizable } from 'react-resizable';
import './index.less';
const { Option } = Select;

const MyTable = ({
  tableChange,
  customRender,
  loading,
  data,
  columnsConfig,
  pagination,
}) => {
  const [paginationSetting, setPaginationSetting] = useState({
    current: 1,
    total: data?.length,
    pageSize: 10,
  });
  // 表格列
  const [cols, setCols] = useState();
  const [columns, setColumns] = useState([]);
  // 调整table表头
  const ResizeableTitle = (props) => {
    const { onResize, width, ...restProps } = props;

    if (!width) {
      return <th {...restProps} />;
    }

    return (
      <Resizable
        width={width}
        height={0}
        onResize={onResize}
        draggableOpts={{ enableUserSelectHack: false }}
      >
        <th {...restProps} />
      </Resizable>
    );
  };
  // 定义头部组件
  const components = {
    header: {
      cell: ResizeableTitle,
    },
  };

  // 处理拖拽
  const handleResize =
    (index) =>
    (e, { size }) => {
      const nextColumns = [...cols];
      // 拖拽是调整宽度
      nextColumns[index] = {
        ...nextColumns[index],
        width: size.width,
      };

      setCols(nextColumns);
    };

  useEffect(() => {
    setColumns(
      (cols || []).map((col, index) => ({
        ...col,
        onHeaderCell: (column) => ({
          width: column.width,
          onResize: handleResize(index),
        }),
      })),
    );
  }, [cols]);

  useEffect(() => {
    generateColumns();
  }, [columnsConfig]);

  // xxx

  const handleChange = (pag) => {
    setPaginationSetting(pag);
  };

  const generateColumns = () => {
    const r = columnsConfig.map((column) => {
      const columnConfig = {
        title: column?.title,
        dataIndex: column?.data_index,
        key: column?.data_index,
        width: column?.width,
      };

      if (column?.filterable) {
        columnConfig.filters = column?.filters;
        // columnConfig.filterDropdown = (filterProps) => (
        //   // 自定义过滤面板的内容
        //   // 使用Select组件展示过滤选项
        //   <div style={{ padding: 8 }}>
        //     <Select
        //       mode="multiple"
        //       style={{ width: "100%" }}
        //       placeholder={`Select ${column.title}`}
        //       value={filterProps.selectedKeys}
        //       onChange={(selectedKeys) =>
        //         filterProps.setSelectedKeys(selectedKeys)
        //       }
        //     >
        //       {column.filters.map((filter) => (
        //         <Option key={filter.value} value={filter.value}>
        //           {filter.text}
        //         </Option>
        //       ))}
        //     </Select>
        //     <Button
        //       type="primary"
        //       onClick={() => filterProps.confirm()}
        //       size="small"
        //       style={{ width: "100%", marginTop: 8 }}
        //     >
        //       Filter
        //     </Button>
        //   </div>
        // );
        columnConfig.onFilter = (value, record) =>
          record[column.data_index]?.toString()?.includes(value);
      }

      if (column.sorter.name) {
        // sorter: "(a, b) => a.name.localeCompare(b.name)",
        if (column.sorter.func === 'localeCompare') {
          columnConfig.sorter = (a, b) =>
            a[column.sorter.name]?.localeCompare(b[column.sorter.name]);
        } else if (column.sorter.func === 'normal') {
          columnConfig.sorter = (a, b) =>
            a[column.sorter.name] - b[column.sorter.name];
        } else {
          columnConfig.sorter = true;
        }
      }

      if (column.render_type === 'text') {
        columnConfig.render = (text, record) => (
          <span
            style={{
              color: column?.color_render && column?.color_render[text],
            }}
          >
            {text}
          </span>
        );
      } else if (column.render_type === 'tag') {
        columnConfig.render = (text, record) => (
          <>
            <Tag key={text} color={column.color_render[text]}>
              {text}
            </Tag>
          </>
        );
      } else if (column.render_type === 'button') {
        columnConfig.render = (text, record) => customRender(text, record);
      }
      return columnConfig;
    });
    setCols(r);
  };
  console.log(columns, components, 'columns');

  return (
    <>
      <div className="components-table-resizable-column">
        <Table
          components={components}
          columns={columns}
          scroll={{ x: true }}
          dataSource={data}
          loading={loading}
          onChange={tableChange}
          pagination={
            pagination === true
              ? undefined
              : {
                  pageSizeOptions: pagination,
                  showSizeChanger: true,
                  showTotal: (total, range) => `共${total}条`,
                  onChange: handleChange,
                  ...paginationSetting,
                }
          }
        />
      </div>
    </>
  );
};

export default MyTable;

I use it like this:

import React, { useState, useEffect } from 'react';
import MyTable from './MyTable';
import { Button, Table } from 'antd';
import ResizeTable from './ResizeTable';
const pagination = true;
function Page2() {
  const [data, setData] = useState([]);
  const [loading, setLoading] = useState(false);
  const [columnsConfig, setColumnsConfig] = useState([]);
  // table
  useEffect(() => {
    setLoading(true);
    // 模拟从后端获取的表格数据
    const dataFromBackend = [
      { key: '1', name: 'John', age: 30, tags: 'success' },
      { key: '2', name: 'Jane', age: 28, tags: 'failed' },
      // 添加更多数据
    ];
    setColumnsConfig([
      {
        title: 'Name',
        data_index: 'name',
        key: 'name',
        width: 100,
        filterable: true,
        filters: [
          { text: 'John', value: 'John' },
          { text: 'Jane', value: 'Jane' },
        ],
        sorter: {
          name: 'name',
          func: 'localeCompare',
        },
        // sorter: "(a, b) => a.name.localeCompare(b.name)",
        render_type: 'text', // 自定义渲染类型标识
        color_render: null,
      },
      {
        title: 'Age',
        data_index: 'age',
        key: 'age',
        width: 100,
        filterable: true,
        filters: [
          { text: '30', value: 30 },
          { text: '28', value: 28 },
        ],
        sorter: {
          name: 'age',
          func: 'normal',
        },
        render_type: 'text', // 自定义渲染类型标识
        color_render: {
          30: 'black',
          28: 'blue',
        },
      },
      {
        title: 'Tags',
        data_index: 'tags',
        key: 'tags',
        width: 100,
        filterable: false,
        filters: null,
        render_type: 'tag', // 自定义渲染类型标识
        // sorter: false,
        sorter: {
          name: 'tags',
          func: 'custom',
        },
        color_render: {
          success: 'green',
          failed: 'red',
        },
      },
      {
        title: 'Actions',
        data_index: 'actions',
        key: 'actions',
        // width: 200,
        sorter: {
          name: 'actions',
          func: 'custom',
        },
        filterable: false,
        filters: null,
        render_type: 'button', // 自定义渲染类型标识
        color_render: null,
      },
    ]);
    setData(dataFromBackend);
    setLoading(false);
  }, []);

  const tableChange = (_pagination, _filter, sorter) => {
    const result = columnsConfig
      ?.filter((i) => i?.sorter?.func === 'custom')
      ?.map((i) => i?.data_index);
    console.log(sorter.columnKey, result);
  };

  const handleAction = (record) => {
    // 处理操作逻辑
    console.log(`Clicked action for ${record.name}`);
  };

  const customRender = (text, record) => (
    <Button onClick={() => handleAction(record)}>Action</Button>
  );


  return (
    <div>
      <h1>React App with Modal</h1>
      <MyTable
        tableChange={tableChange}
        customRender={customRender}
        loading={loading}
        data={data}
        columnsConfig={columnsConfig}
        pagination={true}
      />
      {/* <ResizeTable /> */}
    </div>
  );
}

export default Page2;

the problem is :
image
How can I resolve it?

index.less

  /* 内容过多以...显示 */
  .ellipsisText {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    display: block;
  }
  /* 显示拖拽样式 */
  .react-resizable {
    position: relative ;
    background-clip: padding-box;
  }
  /* 显示拖拽手势 */
  .react-resizable-handle {
    position: absolute;
    width: 10px;
    height: 100%;
    bottom: 0;
    right: 0;
    cursor: col-resize;
    z-index: 6;
    //border-left: white 1px solid;
  }
  .react-resizable-handle:hover {
    //background-color: #69c0ff;
  }

Sorry, I don't think anybody is going to take the time to help you on this if you won't help yourself. Get it down to a much more minimal example and try to ascertain if it's a bug in this library or your code.

It sounds like you're rerendering during a drag event, but I can't be sure.

It's also much easier to communicate about this if you have a working link to a codesandbox.

ok,I know my wrong.my ResizeableTitle component posiiton is wrong.thank you