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'))
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'))
Share
Improve this question
asked Dec 2, 2019 at 4:08
TrevPenningtonTrevPennington
4751 gold badge5 silver badges21 bronze badges
5
-
verify this equality check
coffee[origin] === [byOrigin]
. – Nikhil Koul Commented Dec 2, 2019 at 4:13 -
try this check like this
this.state.coffees.filter(coffee => coffee[origin] === byOrigin)
– Nouman Janjua Commented Dec 2, 2019 at 4:15 -
Try change to
.filter(coffee => coffee.origin === byOrigin)
– thortsx 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 – Nouman Janjua Commented Dec 2, 2019 at 4:20
- Hi Trev, check my solution and let me know if that helps. – ravibagul91 Commented Dec 2, 2019 at 4:36
3 Answers
Reset to default 2You can check like this, please try this.
this.state.coffees.filter(coffee => coffee['origin'] === byOrigin)
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: []
};
}
ponentDidMount() {
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 ponent 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 ponent mount copy original array to a temparary array
ponentDidMount(){
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