How to filter and sort product in ReactJs by Dropdown component of React bootstrap

Viewed 5094

I am creating a filter function for the product list in UI for the user. But I have an issue that, I do not know and never ever try with this function before, so I really difficult to resolve it. I have only 1 day left to do that, so I was very confused

This is my Dropdown Component

import React from "react";
import { Dropdown as BootstrapDropdown } from "react-bootstrap";
import PropTypes from "prop-types";
import "../Dropdown/index.css";

const Dropdown = ({ items }) => {
  return (
    <BootstrapDropdown className="sort-dropdown">
      <BootstrapDropdown.Toggle
        className="sort-dropdown-toggle"
        variant="success"
        id="dropdown"
      >
        <span className="toggle-text">Selection</span>
      </BootstrapDropdown.Toggle>

      <BootstrapDropdown.Menu className="sort-dropdown-menu">
        {items.map((name, index) => (
          <BootstrapDropdown.Item
            className="sort-dropdown-item"
            key={index}
            href={`#/action-${index}`}
          >
            {name}
          </BootstrapDropdown.Item>
        ))}
      </BootstrapDropdown.Menu>
    </BootstrapDropdown>
  );
};

Dropdown.propTypes = {
  items: PropTypes.array,
};

Dropdown.defaultProps = {
  items: [],
};

export default Dropdown;

And this is my page, which the place I get the Dropdown component

import React from "react";
import { Row } from "react-bootstrap";
import Group from "../../../components/Group/index";
import Dropdown from "../../../components/Dropdown/index";
import "../GroupBar/index.css";

const GroupBar = () => {
  return (
    <Row className="group-bar">
      <Group
        title="Product group"
        element={<Dropdown items={["Milk Tea", "Juice"]} />}
      />
      <Group
        title="Sort by price"
        element={<Dropdown items={["Low to hight", "Hight to low"]} />}
      />
    </Row>
  );
}

export default GroupBar;

I would like to filter (by category) and sort (by price) my product page by items of the dropdown. When I select that item, the product will be filtered according to the item I chose.

This is my product list page

import React, { useEffect } from "react";
import { Container, Row, Col } from "react-bootstrap";
import ProductItem from "../../../components/ProductItem/index";
import Loading from "../../../components/Loading";
import PropTypes from "prop-types";
import "../../../common/index.css";
import "../ProductList/index.css";

const ProductList = ({ products, loading, fetchProductRequest }) => {
  useEffect(() => {
    fetchProductRequest();
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  if (loading) {
    return (
      <Container>
        <Row>
          <Col>
            <Loading />
          </Col>
        </Row>
      </Container>
    );
  }
  return (
    <Container>
      <Row>
        {!!products && products.length > 0 ? (
          products.map((product, index) => {
            return (
              <ProductItem
                key={index}
                image={product.image}
                name={product.name}
                price={product.price}
              />
            );
          })
        ) : (
            <h4 className="center-title">Product list is empty!</h4>
          )}
      </Row>
    </Container>
  );
};

export default ProductList;

This is the page for that,

enter image description here

The list of product and the filter/sort are located in the same folder but different files. Like this enter image description here The Group bar it is contain the filter/sort. I get all values by redux, saga

The main page, contain all of them is here

import React from "react";
import { Container } from "react-bootstrap";
import GroupBar from "./GroupBar";
import ProductContainer from "../../containers/ProductContainer";
import Carousel from "../../components/Carousels";
import "../Product/index.css";

const Product = () => {
  return (
    <Container fluid className="p-0">
      <Carousel />
      <Container>
        <GroupBar />
        <ProductContainer />
      </Container>
    </Container>
  );
};

export default Product;

How can I filter related to my list product when it different file like that.

Please anyone help me with this my problem, I just have one day to finish that function, I already research on the internet but it's doesn't make me understand more because it so different from my code and I can not apply that code for mine.

I really really need your support and help as well as you can, the full the better. It's not just helped me to understand also for others like me who are doesn't try it before also see the code is easy to understand too.

I always welcome all of your comments. That is my pleasure. Thank you so much.

1 Answers

You will need your components to keep track of some state. You can read about how to do that here and here.

Once you understand the concept of state, you need to keep track of which item in the list is selected. So for example, you need to keep a state variable that tracks whether "Milk Tea" is selected or "Juice" is selected.

Then, once you have that state, you can display your items using filter or sort on the items list.

Personally, I recommend using class components instead of function components, but here is a minimal working example using function components:

import React, { useState } from 'react';
import { Dropdown as BootstrapDropdown } from 'react-bootstrap';
import './App.css';

const Dropdown = (props) => {
    return (
        <BootstrapDropdown>
            <BootstrapDropdown.Toggle variant='success' id='dropdown'>
                <span>Selection</span>
            </BootstrapDropdown.Toggle>

            <BootstrapDropdown.Menu>
                {props.items.map((name, index) => (
                    <BootstrapDropdown.Item
                        key={index}
                        onClick={(event) => {
                            console.log(event.target.text);
                            props.setSelected(event.target.text);
                        }}
                        value={name}
                    >
                        {name}
                    </BootstrapDropdown.Item>
                ))}
            </BootstrapDropdown.Menu>
        </BootstrapDropdown>
    );
};

function App() {
    const [typeFilter, setTypeFilter] = useState('');

    const allItems = [
        { name: 'Coffee Milk Tea', type: 'Tea' },
        { name: 'Earl Gray Milk Tea', type: 'Tea' },
        { name: 'Orange Juice', type: 'Juice' },
        { name: 'Wheatgrass Juice', type: 'Juice' },
    ];

    const itemsToShow = allItems
        .filter((item) => {
            if (typeFilter) {
                return item.type === typeFilter;
            }
            return true;
        })
        .map((item, i) => {
            return <li key={i}>{item.name}</li>;
        });

    return (
        <div>
            <Dropdown items={['Tea', 'Juice']} setSelected={setTypeFilter} />
            <ol>{itemsToShow}</ol>
        </div>
    );
}

export default App;

Notice that the App component stores the state, and passes its state setter to the Dropdown component. The Dropdown gets the setter in its props and uses it to set the App's state when an option is clicked. The App then uses its state to determine which items to show (using items.filter).

This is an example of Lifting state up. Normally, we would think of tracking which item is selected as the job of the dropdown. But, since we need to access that state in another component, we have to "lift up" that state to something higher in the tree. In this small example case, it was App that stored the state. In general, if the tree looks like this:

  • A
    • B
      • C
      • D
    • E
      • F
        • G
    • H

and you want to share state between G and D, you need to put that state inside of A because A is the closest parent of both G and D. If you want to share state between C and D, then you need to put that state inside B, because B is the parent of C and D.

In reference to the comment below, you probably want to keep the state for which thing in the dropdown is selected inside of your Product component. Then you need to pass the state setter down the props chain all the way into the Dropdown component, which can call that setter and update the state.

Sorry to hear about your tight schedule. Hopefully this answer can be of some use to you.

Related