How to Filter an Array onClick in React

I am trying to filter an array of coffee based on its origin via a button click in React. Right now, whenever a button is clicked the array goes to 0 instead of the desired result of however many items contain the origin clicked. Thanks for your help. Feel free to critique my code as well - I am just beginning!


class Coffee extends React.Component {

  constructor() {
    super();
    this.state = { coffees: [
  {
    name: 'Banko',
    origin: 'Ethiopia',
    price: 16
  },
  {
    name: 'Pueblo',
    origin: 'Costa Rica',
    price: 14
  },
  {
    name: 'Don Pablo',
    origin: 'Columbia',
    price: 13
  },
  {
    name: 'Hava Lama',
    origin: 'Columbia',
    price: 15
  },
  {
    name: 'Guillermo Salva',
    origin: 'Ethiopia',
    price: 19
  },
  {
    name: 'Salla Rosa',
    origin: 'Kenya',
    price: 20
  },
  {
    name: 'Santor Gustavio',
    origin: 'Panama',
    price: 25
      }
     ] 
    }
   }

  handleClick = event => {
    const byOrigin = event.target.value

    const filterCoffee = this.state.coffees.filter(coffee => coffee[origin] === [byOrigin])
    this.setState({coffees: filterCoffee})

  }


  render() {

    const renderAll = this.state.coffees.map(coffee => <li key={Date.now()}>{coffee.name}</li>)


    return (

      <div>
        <button value='all' onClick={this.handleClick}>All</button>
        <button value='Ethiopia' onClick={this.handleClick}>Ethiopia</button>
        <button value='Costa Rica' onClick={this.handleClick}>Costa Rica</button>
        <button value='Kenya' onClick={this.handleClick}>Kenya</button>
        <button value='Columbia' onClick={this.handleClick}>Columbia</button>
        <button value='Panama' onClick={this.handleClick}>Panama</button>


        <p>Coffee: {renderAll}</p>
        <p>{this.state.coffees.length}</p>

      </div>

    )
  }
}

ReactDOM.render(<Coffee />, document.getElementById('root'))

5

3 Answers

You can check like this, please try this.

this.state.coffees.filter(coffee => coffee['origin'] === byOrigin)
2

Optimized way

const buttons = [
  { name: "All", value: "All" },
  { name: "Ethiopia", value: "Ethiopia" },
  { name: "Costa Rica", value: "Costa Rica" },
  { name: "Kenya", value: "Kenya" },
  { name: "Columbia", value: "Columbia" },
  { name: "Panama", value: "Panama" }
];

define button in loop for optimization

        {buttons.map(({ name, value }) => (
          <button
            key={name}
            value={value}
            onClick={this.handleClick.bind(this, name)}
          >
            {name}
          </button>
        ))}

Complete code

const buttons = [
  { name: "All", value: "All" },
  { name: "Ethiopia", value: "Ethiopia" },
  { name: "Costa Rica", value: "Costa Rica" },
  { name: "Kenya", value: "Kenya" },
  { name: "Columbia", value: "Columbia" },
  { name: "Panama", value: "Panama" }
];
class Coffee extends React.Component {
  constructor() {
    super();
    this.state = {
      coffees: [
        {
          name: "Banko",
          origin: "Ethiopia",
          price: 16
        },
        {
          name: "Pueblo",
          origin: "Costa Rica",
          price: 14
        },
        {
          name: "Don Pablo",
          origin: "Columbia",
          price: 13
        },
        {
          name: "Hava Lama",
          origin: "Columbia",
          price: 15
        },
        {
          name: "Guillermo Salva",
          origin: "Ethiopia",
          price: 19
        },
        {
          name: "Salla Rosa",
          origin: "Kenya",
          price: 20
        },
        {
          name: "Santor Gustavio",
          origin: "Panama",
          price: 25
        }
      ],
      filterCoffee: []
    };
  }

  componentDidMount() {
    this.setState({
      filterCoffee: this.state.coffees
    });
  }

  handleClick = name => {
    let filterCoffee = [];
    if (name === "All") {
      filterCoffee = this.state.coffees;
    } else {
      filterCoffee = this.state.coffees.filter(
        coffee => coffee.origin === name
      );
    }

    this.setState({ filterCoffee });
  };

  render() {
    const renderAll = this.state.filterCoffee.map(coffee => (
      <li key={coffee.name}>{coffee.name}</li>
    ));
    return (
      <div>
        {buttons.map(({ name, value }) => (
          <button
            key={name}
            value={value}
            onClick={this.handleClick.bind(this, name)}
          >
            {name}
          </button>
        ))}

        <p>Coffee: {renderAll}</p>
        <h2>{this.state.filterCoffee.length}</h2>
      </div>
    );
  }
}

You should have a separate array of original coffees. On component mount, you must copy your original array into another array and use that array further.

this.state = {
    coffees: [{
            name: 'Banko',
            origin: 'Ethiopia',
            price: 16
        },
        {
            name: 'Pueblo',
            origin: 'Costa Rica',
            price: 14
        },
        {
            name: 'Don Pablo',
            origin: 'Columbia',
            price: 13
        },
        {
            name: 'Hava Lama',
            origin: 'Columbia',
            price: 15
        },
        {
            name: 'Guillermo Salva',
            origin: 'Ethiopia',
            price: 19
        },
        {
            name: 'Salla Rosa',
            origin: 'Kenya',
            price: 20
        },
        {
            name: 'Santor Gustavio',
            origin: 'Panama',
            price: 25
        }
    ],
    filterCoffee: []  //create another array
}

On component mount copy original array to a temparary array

componentDidMount(){
   this.setState({
     filterCoffee: this.state.coffees
   })
}

Now use filterCoffee to render

const renderAll = this.state.filterCoffee.map(coffee => <li key={coffee.name}>{coffee.name}</li>)

Finally on click you must check the condition when you click on all button,

handleClick = event => {
    const byOrigin = event.target.value
    let filterCoffee = []
    if(event.target.value === 'all'){
      //If clicked on all button copy the original array as it is
      filterCoffee = this.state.coffees   
    } else{
      // If clicked on any other button filter the original array based on value
      filterCoffee = this.state.coffees.filter(coffee => coffee.origin === byOrigin)
    } 
    this.setState({filterCoffee})
}

Demo

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Sarah Jenkins

Sarah Jenkins

Senior Technology Editor & AI Specialist

Sarah Jenkins is a veteran tech journalist with over 12 years of experience covering artificial intelligence, mobile innovations, and digital ethics. Her insights have appeared in leading technology publications worldwide.

Share this article
Twitter Facebook Pinterest