【问题标题】:Arrays - Javascript - filter array of objects using input search数组 - Javascript - 使用输入搜索过滤对象数组
【发布时间】:2017-08-17 13:32:15
【问题描述】:

我正在尝试使用 react 过滤列表,但令人惊讶的是,对于这样一个常见的任务,在网上找不到任何东西来帮助我实现这一点。

我有一组用户,然后我想过滤它们(从名称开始 - 我可以按年龄进行过滤)。 该数组在我的 redux 存储中,如下所示。

let users = [
  {
    name: 'Raul',
    age: 29
  },
  {
    name: 'Mario',
    age: 22
  }
];

我的整个组件如下所示。

class Test extends Component {

    constructor(props) {
        super(props);

        this.state = {
            users: this.props.users

        };

        this.filterList = this.filterList.bind(this);

    }

    componentWillReceiveProps(nextProps) {

        this.setState({
            users: nextProps.users
        });

    }

    filterList(event) {

        let users = this.state.users;
        users = users.filter(function(user){
        //unsure what to do here
        });
        this.setState({users: users});
    }

  render(){

    const userList = this.state.users.map((user) => {
      return <li>{user.name} {user.age}</li>;
    });

    return(
      <input type="text" placeholder="Search" onChange={this.filterList}/>
      <ul>
        { userList }
      </ul>
    );

  }
}

【问题讨论】:

  • 过滤条件是什么?
  • 道歉@pablogq 按名称过滤。理想情况下两者都可以,但可以以名称开头

标签: javascript arrays reactjs ecmascript-6


【解决方案1】:

如果您想过滤name,您可以使用.filter.startsWith.indexOf 一起为给定用户返回真或假。

您还在 onChange 事件上设置了一个新的用户列表,这迟早会导致一个空数组。这里我使用了仅由道具改变的user 状态,以及在击键发生时改变的filteredUsers

class Test extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      users: this.props.users,
      filteredUsers: this.props.users,
      q: ''
    };

    this.filterList = this.filterList.bind(this);
    this.onChange = this.onChange.bind(this);
  }

  componentWillReceiveProps(nextProps) {
    this.setState(
      {
        users: nextProps.users,
        filteredUsers: nextProps.users
      },
      () => this.filterList()
    );
  }

  onChange(event) {
    const q = event.target.value.toLowerCase();
    this.setState({ q }, () => this.filterList());
  }

  filterList() {
    let users = this.state.users;
    let q = this.state.q;

    users = users.filter(function(user) {
      return user.name.toLowerCase().indexOf(q) != -1; // returns true or false
    });
    this.setState({ filteredUsers: users });
  }

  render() {
    const userList = this.state.filteredUsers.map(user => {
      return <li>{user.name} {user.age}</li>;
    });

    return (
      <div>
        <input
          type="text"
          placeholder="Search"
          value={this.state.q}
          onChange={this.onChange}
        />
        <ul>
          {userList}
        </ul>
      </div>
    );
  }
}

const userList = [
  {
    name: 'Raul',
    age: 29
  },
  {
    name: 'Mario',
    age: 22
  }
];

ReactDOM.render(<Test users={userList} />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>

【讨论】:

  • 索引看起来如何?
  • 你可以在那里做一个 if 语句。如果.indexOf(q) 的结果是-1,则返回false。否则,返回真。或user.name.toLowerCase().indexOf(q) != -1 一行完成。
  • 谢谢!只有一个问题!用户数组不断增长,因此当添加更多用户时,它们不会显示。你知道我怎么能解决这个问题吗?!
  • 更新了我的答案。当组件接收到新的 props 时,您还想更新 filteredUsers 状态。此外,您可能希望根据您想要的行为再次手动调用filterList
  • 这是我已经尝试过的,但这会破坏过滤器搜索,因为当将新用户添加到数组时会再次显示整个数组。明白我的意思吗?
【解决方案2】:

您还需要一个state 变量来存储搜索结果,用相同的数据初始化该变量,一旦用户键入任何内容,将过滤后的数据存储在其中,试试这个:

let users = [
  {
    name: 'Raul',
    age: 29
  },
  {
    name: 'Mario',
    age: 22
  }
];

class Test extends React.Component {

    constructor(props) {
        super(props);

        this.state = {
            users: users,
            result: users,
        };

        this.filterList = this.filterList.bind(this);

    }

    componentWillReceiveProps(nextProps) {

        this.setState({
            users: nextProps.users,            
        });

    }

    filterList(event) {
        let value = event.target.value;
        let users = this.state.users, result=[];
        result = users.filter((user)=>{
            return user.name.toLowerCase().search(value) != -1;
        });
        this.setState({result});
    }

  render(){

    const userList = this.state.result.map((user) => {
      return <li>{user.name} {user.age}</li>;
    });

    return(<div>
      <input type="text" placeholder="Search" onChange={this.filterList}/>
      <ul>
        {userList}
      </ul>
      </div>
    );

  }
}

ReactDOM.render(<Test/>, document.getElementById('app'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>


<div id='app'></div>

【讨论】:

    【解决方案3】:
    let datas =[
      {   
          "id":1,
          "title":"Ucat",
          "handle":"mi"
      },
      {
          "id":2,
          "title":"Acat",
          "handle":"csk"
      },
      {
          "id":3,
          "title":"Vcat",
          "handle":"kkr"
      },
      {
          "id":4,
          "title":"Atar",
          "handle":"pkbs"
      }];
    const [search, setSearch] =useState(datas);
    const handleInputChange = (e) => {
    var dm = e.target.value;
    var str =dm.toString();
    var debug = datas.filter(x=> x["title"].toLowerCase().includes(str));
    setSearch(debug);};
    
    
    <input type="text"  onChange={handleInputChange}/>
    {search.map((item)=>(
        <div key={item.id}>
            <ul>
                <li>
                {item.handle} 
                <br/>
                {item.title}
                </li>
            </ul>
        </div>
    ))};
      
      
    

    【讨论】:

    • 发布答案时请提供相关解释,以便提问者更好地理解解决方案
    【解决方案4】:

    如果您想过滤列表,您必须有一个过滤条件。例如你有一个变量let filterAge = 18;

    在这种情况下,您可以使用该值过滤用户列表

    let users = users.filter(function(user){
        //return all users older or equal to filterAge
        return user.age >= filterAge;        
    });
    

    函数的每个结果等于 true,都将添加到 users 变量中。虚假的回报将把它排除在外。如何确定真/假取决于您。硬编码它(不是很有用),一个简单的等号语句(如上)或一个做高等数学的函数。你的选择。

    【讨论】:

    • codepen.io/pjmtokyo/pen/ZGVjVV 这个似乎是根据具体情况进行的,没有像 if user is older than 18 那样明确的东西
    • 你能看到search是在哪里定义的吗?
    • 好吧,他在这里指定使用函数来确定(小写)名称是否具有给定的值(小写),使用搜索功能。
    • 啊是啊,不知道有一个js search 方法。随时更新你的答案,我可以给你一个绿色的勾
    • 他正在使用默认的javascript字符串搜索功能。有关详细信息,请参阅w3schools.com/jsref/jsref_search.asp。如果该字符串包含给定值,则返回字符串中该值开始的位置。如果它在开头,则该值返回 0。如果它不在其中,则返回 -1。但总的来说,他将搜索值与过滤器函数中的每个项目进行匹配。
    【解决方案5】:

    这样对我来说总是很有效。

    const [data, setData] = useState([{name: 'Kondo'}, {name: 'Gintoki'}])
    
    const handleFilterFilesTable = () => {
        return data
          .filter((element) => {
            if (searchText !== "") {
              return element?.name?.toLowerCase()?.includes(searchText?.toLowerCase())
            }
    
            return element
          })
      }
    
    // ...
    return (
     //...
     <Table data={handleFilterFilesTable()} />
    )
    

    这样我就可以应用多个过滤器一起工作,只需像这样扩展 filter 方法

    // ...
    return data.filter().filter().filter()//...
    // ...
    

    【讨论】:

      猜你喜欢
      • 2021-12-16
      • 2020-05-30
      • 1970-01-01
      • 2015-12-17
      • 1970-01-01
      • 2018-12-25
      • 2022-01-02
      • 2012-11-15
      相关资源
      最近更新 更多