Paweł Stanecki
Paweł Stanecki

Reputation: 454

Filtering object list with React

It could be a clone post but I did not find any solution for in my case. I have list of an objects:

export default function() {
  return [
    {name: 'Mark Teer Stegen'},
    {name: 'Nelson Semedo'},
    {name: 'Gerrard Pique'},
    {name: 'Ivan Rakitic'},
    {name: 'Sergio Busquets'},
    {name: 'Denis Suarez'},
    {name: 'Coutinho'},
    {name: 'Luis Suarez'},
    {name: 'Lionel Messi'},
    {name: 'Dembele'},
    {name: 'Malcom'}
  ]
}

I import it to the component, assign to the state and displaying it in the component below.

import React, {Component} from 'react';
import {connect} from 'react-redux';

class Barca extends Component{
  constructor(props){
    super(props);

    this.state = {
      players: this.props.players,
      player: '' //empty to set as an input
    }
  }

  onChange(e){
    this.setState({
      player: e.target.value
    });
    console.log(this.state.player);
  }
  renderList(){
    return this.state.players.map((player) => {
      return(
        <tr key={player.name}>
          <td>{player.name}</td>
        </tr>
      );
    });
  }
  render(){
    return(
      <div className="col-sm-6 table-col table-responsive">
        <input
          type="text"
          value={this.state.player}
          onChange={this.onChange.bind(this)}
        />
        <table className="table table-striped">
          <thead>
            <tr>
              <th className="text-center">
                FC Barcelona
              </th>
            </tr>
          </thead>
          <tbody>
            {this.renderList()}
          </tbody>
        </table>
      </div>
    );
  }
}

const mapStateToProps = (state) => {
  return {
    players: state.reducerBarca
   };
};


export default connect(mapStateToProps)(Barca);

List looks like that

list view

The problem is that I would like to filter my players list by the value from input. I have done some research here and I have only found filtering in Array, not like I have in Objects list.

What I have done for now:

  1. displaying the players list
  2. Geting the value from the input and displaying it after every written letter
  3. How to render my list by the inputted term ???

Thank you all people ! I have removed the players state

constructor(props){
    super(props);

    this.state = {
      //players: this.props.players <-- Stupid thing
      player: '' //empty to set as an input
    }
  }

and rewrite my renderList() function

return this.props.players.filter(player =>
        player.name.toLowerCase().includes(this.state.player.toLowerCase())).map(searchedPlayers => {
          return(
            <tr key={searchedPlayers.name}>
              <td>{searchedPlayers.name}</td>
            </tr>
          );
        })
    }

Upvotes: 7

Views: 28485

Answers (3)

Bhojendra Rauniyar
Bhojendra Rauniyar

Reputation: 85545

You can use filter:

renderList(){
    const { player } = this.state
    const { players } = this.props
    // ignore user's typing case
    const iPlayer = player.toLowerCase()
    const filteredPlayers = players.filter(p => 
       p.name.toLowerCase().includes(iPlayer)
    )
    // now, map to the filteredPlayers

Upvotes: 2

Gavin Thomas
Gavin Thomas

Reputation: 1867

this.state.players.filter(player => player.name.includes(this.state.player))

And if you wanted to then map them instead of just filtering the state...

this.state.players.filter(player => 
player.name.includes(this.state.player)).map(searchedPlayers => {
  return(
    <tr key={searchedPlayers.name}>
      <td>{searchedPlayers.name}</td>
    </tr>
  );
})

Note you can also render straight from props without setting to state, (to avoid re-renders every-time the user types) by replacing

this.state.players

with

this.props.players

Upvotes: 10

Gurpreet Singh
Gurpreet Singh

Reputation: 209

You don't need to use copy state to props, you can use this.props.players as well.

getPlayers() {
  if(this.state.player) {
    return this.state.players.filter(player => player.name.includes(this.state.player))
  } else {
    return this.state.players
  }
}

Then you can call let collection = getPlayers(); and map the players to html content.

Upvotes: 0

Related Questions