首页 > 解决方案 > 在拖放从列表中选择一个项目时,它会再次出现在搜索中

问题描述

我有一个带有搜索功能的 dnd 选择选项卡来过滤可用的项目。一旦从可拖动部分中选择了一个项目,它应该从该部分中删除并放置到可放置部分,反之亦然。我的代码的链接是https://codesandbox.io/s/dnd-search-select-sort-xfdtn 当一个项目说“Apple”被选中时,它会进入可放置部分但是当我再次搜索“Apple”时在可拖动部分搜索栏中,它再次出现,我可以再次将其移动到不应该出现的可放置部分。一旦它被选中,它就不应该再次出现在列表中。下面是对应的代码。

import React from "react";
import { Icon, Col, Input, Card, Tooltip, Tabs } from "antd";
import "ant-design-draggable-modal/dist/index.css";
import { Scrollbars } from "react-custom-scrollbars";
import Fuse from "fuse.js";

const { TabPane } = Tabs;

const { Search } = Input;
const items = [
  {
    values: ["false", "true"],
    cleanTitle: "Apple",
    columnName: "apple",
    type: "fruit"
  },
  {
    values: ["false", "true"],
    cleanTitle: "Mango",
    columnName: "mango",
    type: "fruit"
  },
  {
    values: ["false", "true"],
    cleanTitle: "Berry",
    columnName: "berry",
    type: "fruit"
  },
  {
    values: ["false", "true"],
    cleanTitle: "Orange",
    columnName: "orange",
    type: "fruit"
  },
  {
    values: ["false", "true"],
    cleanTitle: "Litchi",
    columnName: "litchi",
    type: "fruit"
  },
  {
    values: ["false", "true"],
    cleanTitle: "Pineapple",
    columnName: "pineapple",
    type: "fruit"
  }
];
class ItemSelection extends React.Component {
  state = {
    visible: true,
    items: items,
    selected: [],
    fuzzySearcher: new Fuse(items, { keys: ["cleanTitle"] })
  };

  handleItemSelect = selectedSegmentIndex => {
    let { items, selected } = this.state;
    const [removed] = items.splice(selectedSegmentIndex, 1);
    selected.splice(selected.length, 0, removed);
    this.setState({ items, selected });
  };
  handleItemUnselect = unselectedSegmentIndex => {
    let { items, selected } = this.state;
    const [removed] = selected.splice(unselectedSegmentIndex, 1);
    items.splice(items.length, 0, removed);
    this.setState({ items, selected });
  };
  handleItemUnselect = (index, dir) => {
    let { selected } = this.state;
    selected.splice(index, 0, selected.splice(index + dir, 1)[0]);
    this.setState({ selected });
  };
  handleItemSearch = searchText => {
    searchText !== "" &&
      this.setState({ items: this.state.fuzzySearcher.search(searchText) });
  };
  handleItemMove = (index, dir) => {
    let { selected } = this.state;
    selected.splice(index, 0, selected.splice(index + dir, 1)[0]);
    this.setState({ selected, defaultChanged: true });
  };
  render() {
    const { tabKey } = this.props;
    return (
      <Tabs type="card" defaultActiveKey={tabKey}>
        <TabPane tab="Select Items" key="2">
          <div className="item-dnd">
            <Col span={12}>
              <Card className="droppable-item-card" title="Available items">
                <Search
                  className="search-fuzzy-item"
                  allowClear={true}
                  placeholder="Search for a fruit"
                  onChange={e => this.handleItemSearch(e.target.value)}
                />
                <div className="droppable-item-left">
                  <Scrollbars style={{ height: 300 }}>
                    {this.state.items &&
                      this.state.items.map((item, index) => (
                        <Col span={24} key={item.columnName}>
                          <div
                            className="draggable-item"
                            key={`source-${index}`}
                          >
                            {item.cleanTitle}
                            <Tooltip
                              placement="bottom"
                              title={<span>Select</span>}
                            >
                              <span
                                className={
                                  this.state.selected.length < 4
                                    ? "item-move-icon-right"
                                    : "item-move-icon-right-disabled"
                                }
                              >
                                <Icon
                                  type="caret-right"
                                  onClick={() => {
                                    this.state.selected.length < 4
                                      ? this.handleItemSelect(index)
                                      : null;
                                  }}
                                />
                              </span>
                            </Tooltip>
                          </div>
                        </Col>
                      ))}
                  </Scrollbars>
                </div>
              </Card>
            </Col>
            <Col span={12}>
              <Card
                className="droppable-item-card"
                title={`Selected Items (${this.state.selected.length})`}
              >
                <div className="droppable-item-right">
                  {this.state.selected.map((item, index) => (
                    <div className="draggable-item" key={`target-${index}`}>
                      <Tooltip
                        placement="bottom"
                        title={<span>Un-select</span>}
                      >
                        <span className="item-move-icon-left">
                          <Icon
                            type="caret-left"
                            onClick={() => {
                              this.handleItemUnselect(index);
                            }}
                          />
                        </span>
                      </Tooltip>
                      {item.cleanTitle}
                      <span className="item-move-icon-right">
                        {index > 0 && (
                          <Icon
                            type="caret-up"
                            onClick={() => {
                              this.handleItemMove(index - 1, 1);
                            }}
                          />
                        )}
                        {index < this.state.selected.length - 1 && (
                          <Icon
                            type="caret-down"
                            onClick={() => {
                              this.handleItemMove(index + 1, -1);
                            }}
                          />
                        )}
                      </span>
                    </div>
                  ))}
                </div>
              </Card>
            </Col>
          </div>
        </TabPane>
      </Tabs>
    );
  }
}

export default ItemSelection;

标签: javascriptreactjslistfilter

解决方案


在您所在的州,您Fuse使用完整列表创建一次实例items。在你的handleItemSearch你总是搜索完整的列表items。因此问题。

要解决此问题Fuse请在您的handleItemSearch

handleItemSearch = searchText => {
    // this.setState({ items: this.state.fuzzySearcher.search(searchText) }); //<--- don't do this

    this.setState(({items}) => ({ items: new Fuse(items, { keys: ["cleanTitle"] }).search(searchText) }));
  };

工作演示在这里


推荐阅读