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')) 53 Answers
You can check like this, please try this.
this.state.coffees.filter(coffee => coffee['origin'] === byOrigin) 2Optimized 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}) }