0

I'm working on practicing with React and I'm creating a drop down menu, but in that when a user clicks on either a fruit or a vegetable, it'll filter and show on the page which item was selected.

I'm a little confused as my thought process was creating the changeItem method to filter out those specific items and call that as apart of the onChange in the HTML render, but I'm not sure if this is the correct way of approaching this and it's currently not rendering anything at the moment.

Any guidance would be appreciated

This is the code that I have so far:

class ItemList extends React.Component {
  constructor(props) {
    super(props)
this.changeItem = this.changeItem.bind(this)
this.state = {
value: 'all' // this would be the initial value
}
    changeItem(event) {
this.setState({value: event.target.value} // where the value will be changed 
}
  }

  render() {
    return (
      <>
      <select onChange={this.changeItem} value:{event.target.value}>
        <option value='all'>all</option>
        <option value='cats'>fruits</option>
        <option value='dogs'>vegetables</option>
      </select>
        <div className="item-list">
          {this.props.items.map((item) =>
          <SingleItem key={item.id}
          item={item} />
          )}
        </div>
      </>
    );
  }
}

2 Answers2

0

I have prepared a sample which I think it will help you

import React from "react";

function SingleItem({ item }) {
  return <div>{item?.type}</div>
}

class ItemList extends React.Component {
  currentType = "";

  constructor(props) {
    super(props)
    this.changeItem = this.changeItem.bind(this)
    this.state = {
      currentType: "all"
    }
  }

  changeItem(event) {
    this.setState({ currentType: event.target.value }) // where the value will be changed 
  }

  filter(list) {
    switch (this.state.currentType) {
      case "cats":
        return list.filter(i => i.type === "cats");
      case "dogs":
        return list.filter(i => i.type === "dogs");
      default:
        return list;
    }
  }

  render() {
    return <React.Fragment>
      <select onChange={this.changeItem}>
        <option value='all'>all</option>
        <option value='cats'>fruits</option>
        <option value='dogs'>vegetables</option>
      </select>
      <div className="item-list">
        {this.props.items && this.filter(this.props.items).map((item) => <SingleItem key={item.id} item={item} />
        )}
      </div>
    </React.Fragment>
  }
}

export default function Page() {
  let items = [
    {
      id: 1,
      type: "cats",
      name: "black cat"
    },
    {
      id: 2,
      type: "cats",
      name: "white cat"
    },
    ,
    {
      id: 3,
      type: "dogs",
      name: "Yellow dog"
    }
  ];

  return <ItemList items={items} />
}
Tran Loc
  • 433
  • 2
  • 7
0

I see a few different questions here, but I'll try to explain everything in a way that makes sense.

I'm going to suggest using functional components over class components. There's more explanation about the reasoning to using functional components in this answer as well, but to be brief here, the reasoning as explained in the linked answer is summarized as:

With the introduction of React hooks, it seems as though the React teams wants us to use functional components whenever possible (which better follows JavaScript's functional nature).

1.) It’s hard to reuse stateful logic between components 2.) Complex components become hard to understand 3.) Classes confuse both people and machines

First, we need an array of the possible options for the select menu:

const items = ["cats", "dogs"];

Next, we'll define the SingleItem component as simply as possible for the sake of this example:

function SingleItem({ item }) {
  return <div>{item}</div>;
}

Then inside of ItemList we use useState to create a state variable so we can keep track of which item the user has selected:

function ItemList() {
  const [selectedItem, setSelectedItem] = useState("all");
...

We also need to create a filtered version of the default list of items so that we can show only the selected item, or all items if "all" is selected:

  const filteredItems = items.filter(
    (item) => selectedItem === "all" || selectedItem === item
  );

Then in our select, we set the value prop to the data saved in the selectedItem state variable. We also set the onChange prop to a function that will update selectedItem whenever the user selects a new item:

<select
        onChange={(e) => setSelectedItem(e.target.value)}
        value={selectedItem}
>
        <option value="all">all</option>
        <option value="cats">cats</option>
        <option value="dogs">dogs</option>
</select>

Finally, we display the list items which should be shown by displaying each item in our filteredItems list:

      <div className="item-list">
        {filteredItems.map((item) => (
          <SingleItem key={item.id} item={item} />
        ))}
      </div>

Here's a full working example on codesandbox: Edit optimistic-frost-w5f37w

Andrew Hulterstrom
  • 1,563
  • 4
  • 18