Reputation: 25
I have the following code and need to add two extra things to it but I'm stuck and not sure how to do it.
I need to add:
If there are no products in the category a NotFound component will show a message.
By typing 'all' in the input we should be able to see the entire list of products again from all the categories.
Ideally I'm looking for the simplest solution as I'm currently learning React. Thanks!
Main Component
import React from 'react';
import Item from './components/Item';
class App extends React.Component {
state = {
items: [
{
title: "The Spice Girls",
price: 10,
category: "Pop",
quantity: 1,
},
{
title: "Beethoven",
price: 5,
category: "Classical",
quantity: 1,
},
{
title: "Bob Marley",
price: 15,
category: "Reggae",
quantity: 1,
}
],
category: " ",
filtered: [],
}
handleChange = e => {
this.setState({category: e.target.value},()=>console.log(this.state.category));
}
handleClick = (event) => {
event.preventDefault()
var newList = this.state.items;
var filteredItems = newList.filter(item => item.category === this.state.category)
this.setState({filtered: filteredItems})
}
render () {
let show;
if(this.state.category !== " "){
show = this.state.filtered.map((item, i) => <Item key = {i} cd={item}/>)
}else{
show = this.state.items.map( (item,i) => <Item key = {i} cd={item}/>)
}
return (
<div>
<h1 className = "title">CD</h1>
<h2>Search music below:</h2>
<form>
Music style: <input onChange = {this.handleChange}></input>
<button onClick = {this.handleClick}>Search</button>
</form>
{show}
</div>
)
}
}
export default App;
Item Component
import React from 'react';
class Item extends React.Component {
render () {
return (
<div className = "items">
<div className = "item">
<h3>{this.props.cd.title}</h3>
<div className = "price">Price: {this.props.cd.price}€</div>
<div className = "quantity">Quantity: {this.props.cd.quantity}</div>
<div className = "category">Category: {this.props.cd.category}</div>
</div>
</div>
)
}
}
export default Item;
Upvotes: 1
Views: 420
Reputation: 4839
There are a few things which confused me much when analysing your code, so will share them with you, as if in the future you work on teams, it would be handy if other people can understand your code.
You have an on change event for the text box which is different to the event for the search button next to it. Users would expect it to be the same and so that's really confusing.
You have 2 lists of items essentially, a raw and unfiltered and you switch between which 2 to present on the screen. Sometimes you need to have a raw set and that's fine, but perhaps make sure that the only ones which are presented as such
is just either the state.items
or the state.filtered
. I would probably expect the state.filtered
Make your search case insensitive, e.g. pop should match Pop
If there are no products in the category a NotFound component will show a message.
For this I would first modify your show logic to work on the same filtered list just change your event functions to manipulate the filtered list and untouch the items one.
add another condition perhaps for when there are no cases
if (this.state.filtered) {
show = this.state.filtered.map((item, i) => <Item key={i} cd={item} />);
} else {
show = <h1>NoneFound</h1>;
}
By typing 'all' in the input we should be able to see the entire list of products again from all the categories.
handleClick = event => {
event.preventDefault();
var { category } = this.state;
var newList = this.state.items;
var filteredItems;
if ([" ", "All"].some(t => t === category)) {
filteredItems = newList;
} else {
filteredItems = newList.filter(
item => item.category.toLowerCase() === this.state.category.toLowerCase()
);
}
this.setState({ filtered: filteredItems });
};
My souloution to this was to modify your onClick event to correctly manipulated the filtered list.
You can see my full soloution to this on my codesandbox here
Upvotes: 1