Cristina
Cristina

Reputation: 25

React - conditional/message

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:

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

Answers (1)

Max Carroll
Max Carroll

Reputation: 4839

First of all some suggested changes before I answer your question

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

Answer to your question'ss

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

Edit Autocomplete

Upvotes: 1

Related Questions