使用多个过滤器重新渲染组件

时间:2018-11-24 18:45:58

标签: javascript reactjs

我在应用程序中使用过滤器,该过滤器限制了用户列表的输出。在我的codesandbox

中查看具有相同概念的示例

这个想法是该列表接受多个过滤器值以根据需要缩小搜索范围。输入任何字符时,第一个过滤器工作正常,但是在第二个过滤器输入中进行切换然后再键入一些内容,则会重新呈现列表并覆盖第一个过滤器的搜索结果。

主要组件:

  <div className="App">
    <Filters onChange={this.handleFilter} />
    <div className="list">
      <List users={filteredUsers} />
    </div>
  </div>

过滤器输入:

<div className="filters">
  <input
    name="name"
    type="text"
    placeholder="Search by name"
    onChange={props.onChange}
  />
  <input
    name="email"
    type="text"
    placeholder="Search by email"
    onChange={props.onChange}
  />
</div>

过滤器处理程序:

  handleFilter = event => {
    const target = event.target;
    let updateUsers = this.state.users;
    updateUsers = updateUsers.filter(user => {
      let type;
      if (target.name === "name") {
        type = user.name;
      } else if (target.name === "email") {
        type = user.email;
      }
      return type.toLowerCase().search(target.value.toLowerCase()) !== -1;
    });
    this.setState({ filteredUsers: updateUsers });
  };

我确实计划使用更多的过滤器,并且该列表不应重新呈现。 有什么方法可以防止这种情况或制定出更好的解决方案? 大型网站如何应用其过滤器?

2 个答案:

答案 0 :(得分:0)

您可以将电子邮件的过滤器值和名称都设置为状态,然后触发一个过滤器功能,将这两个值用于最终结果。您还应该以组件或父组件的状态存储filter的值。这样一来,您就不会覆盖您的搜索值。

import React, { Component } from "react";

const Filters = ({ onChange, emailFilterValue, nameFilterValue }) => (
  <div className="filters">
    <input
      name="name"
      type="text"
      placeholder="Search by name"
      onChange={onChange}
      value={nameFilterValue}
    />
    <input
      name="email"
      type="text"
      placeholder="Search by email"
      onChange={onChange}
      value={emailFilterValue}
    />
  </div>
);

class Main extends Component {
  constructor(props) {
    super(props);
    this.state = {
      users: [],
      nameFilter: "",
      emailFilter: ""
    };
  }

  handleFilter = e => {
    const { name, value } = e.target;
    if (name === "email") {
      this.setState({ emailFilter: value });
    } else if (name === "name") {
      this.setState({ nameFilter: value });
    }
    this.filterUsers();
  };

  filterUsers = () => {
    const { users, nameFilter, emailFilter } = this.state;
    let updateUsers = users.slice();
    if (nameFilter.length > "") {
      // do your search based on name
    }
    if (emailFilter.length > "") {
      // then apply email filter
    }
    this.setState({ users: updateUsers });
  };

  render() {
    return (
      <div className="App">
        <Filters
          onChange={this.handleFilter}
          emailFilterValue={this.state.emailFilter}
          nameFilterValue={this.state.nameFilter}
        />
        <div className="list">
          <List users={filteredUsers} />
        </div>
      </div>
    );
  }
}

答案 1 :(得分:0)

这里是my solution的示例。通常,“大型网站”在不必要时会尽可能减少过滤时间。同样,我将添加一个setTimeout()以便不立即对每个输入进行过滤,并且如果用户在400毫秒内键入(例如),则清除所述超时。

在您的过滤器组件中,我会跟踪过滤后的单词:

class Filters extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      email: "",
      name: ""
    };
  }

  handleChange = event => {
    const { onChange } = this.props;
    let key = "email";
    if (event.target.name === "name") {
      key = "name";
    }

    this.setState({ [key]: event.target.value });

    onChange({ email: this.state.email, name: this.state.name });
  };

  render() {
    const { onChange } = this.props;
    return (
      <div className="filters">
        <input
          name="name"
          type="text"
          placeholder="Search by name"
          onInput={this.handleChange}
        />
        <input
          name="email"
          type="text"
          placeholder="Search by email"
          onInput={this.handleChange}
        />
      </div>
    );
  }
}

然后在您的App组件中,我将创建两个不同的过滤器,这样,如果填写了“ name”属性,它将优先考虑:

handleFilter = data => {
    let updateUsers = this.state.users;
    console.log(data);

    if (data.name.length > 0) {
      updateUsers = updateUsers.filter(user => {
        return user.name.toLowerCase().includes(data.name);
      });
    }

    if (data.email.length > 0) {
      updateUsers = updateUsers.filter(user => {
        return user.email.toLowerCase().includes(data.email);
      });
    }

    this.setState({ filteredUsers: updateUsers });
  };