1

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
  • verify this equality check coffee[origin] === [byOrigin]. Commented Dec 2, 2019 at 4:13
  • try this check like this this.state.coffees.filter(coffee => coffee[origin] === byOrigin) Commented Dec 2, 2019 at 4:15
  • Try change to .filter(coffee => coffee.origin === byOrigin) Commented Dec 2, 2019 at 4:15
  • One more thing, once this array is filtered by a origin, than you will not be able to get data for other origins Commented Dec 2, 2019 at 4:20
  • Hi Trev, check my solution and let me know if that helps. Commented Dec 2, 2019 at 4:36

3 Answers 3

2

You can check like this, please try this.

this.state.coffees.filter(coffee => coffee['origin'] === byOrigin)
Sign up to request clarification or add additional context in comments.

2 Comments

This provides a partial answer.
Why are you booing me? I m right. I just point where he is making a mistake and yes I respect your opinion.
0

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>
    );
  }
}

Comments

0

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.