首页 > 解决方案 > 如何使过滤和搜索协同工作?

问题描述

我有一个组件:

export default class Shop extends PureComponent {
  state = {
    search: "",
    filters: [],
    items: json
  };


  onFilterChange = ( event ) => {
    const checkboxes = [...event.currentTarget.closest(".filter").getElementsByTagName("input")]
    const filters = [];
    checkboxes.map(checkbox => {
      if (checkbox.checked) {
        filters.push(checkbox.name);
      }
    });
    this.setState({ filters }, this.filtredInput);
  }


  filtredInput() {
    let items = json

    if (this.state.filters.length !== 0) {
      items = items.filter(element => this.state.filters.every(key => element[key]));
    }


    if (this.state.search.length !== 0) {
      items = items.filter(word =>
        word.name.toLocaleLowerCase().indexOf(this.state.search.toLocaleLowerCase()) !== -1
      )
    }

    this.setState( {items} )
  }

  onSearchChange = ( {currentTarget} ) => {
    const search = currentTarget.value
    this.setState({ search }, this.filtredInput() )
  }

  render() {
    return (
      <div>
        <div className="navigation">
          <Filter
            onFilterChange={this.onFilterChange}
          />
          <Search
            onSearchChange={this.onSearchChange}
          />
        </div>
        <Filtered
              items={this.state.items}
              updateShoppingBasket={this.updateShoppingBasket}
            />
      </div>
    )
  }
}

帮助组织逻辑,使搜索和过滤器同时工作。就个人而言,一切正常。但在当前版本中,搜索工作好像有延迟(显然,代码在设置状态之前工作),但我不确定是否有其他错误。React中如何正确组织过滤器+搜索的逻辑?

标签: reactjs

解决方案


通过以不同的方式思考数据,您可以让这一切变得更轻松。如果您要求始终存储最新的过滤数据,那么这将不起作用。我在这里包含了一个自定义代码示例(包括示例所依赖的组件):https ://codesandbox.io/s/hardcore-cohen-sg263?file=/src/App.js

我喜欢考虑我们需要存储以执行操作的三段数据。

  1. 搜索词
  2. 过滤器列表
  3. 我们要过滤和搜索的项目列表

如果需要,我们可以从 API 下载项目列表,这样我们就可以通过过滤和替换来确保我们永远不会丢失数据。

export default class App extends React.Component {
  /*
    there are three things we store

    1. the current search term
    2. the current list of filters
    3. the entire list of data we want to search and filter through
       (this can start as an empty array and then be filled with data from an API)
  */
  state = {
    term: "",
    filters: [],
    list: [
      {
        color: "red",
        name: "car"
      },
      {
        color: "blue",
        name: "plane"
      },
      {
        color: "red",
        name: "boat"
      }
    ]
  };

  /* This handles toggling filters, when the filter is clicked it will check
     the array and add it if it isn't there.
  */
  toggleFilter = filter => {
    if (this.state.filters.includes(filter)) {
      this.setState({
        filters: this.state.filters.filter(item => item !== filter)
      });
    } else {
      this.setState({
        filters: [...this.state.filters, filter]
      });
    }
  };

  updateTerm = term => {
    this.setState({
      term
    });
  };

  /* selector function to filter a list of items */
  applyFilters = list => {
    if (this.state.filters.length === 0) {
      return list;
    }

    return list.filter(item => this.state.filters.includes(item.color));
  };

  /* search function to filter for the search term */
  applySearch = list => {
    if (this.state.term === "") {
      return list;
    }

    return list.filter(item => item.name.startsWith(this.state.term));
  };

  render() {
    /* we can filter the list and then search through the filtered list */
    const filteredItems = this.applyFilters(this.state.list);
    const searchedItems = this.applySearch(filteredItems);

    /* we pass the filtered items to the list component */
    return (
      <>
        <Filters onChange={this.toggleFilter} />
        <Search term={this.state.term} onChange={this.updateTerm} />
        <List items={searchedItems} />
      </>
    );
  }
}

希望这有助于为 React 建立一个不同的心智模型。我故意避免让过滤器成为受控组件,而只是为了向您展示渲染函数中的过滤器。始终开放讨论。让我知道事情的后续。


推荐阅读