J
J
JekaHC2022-04-01 10:05:20
JavaScript
JekaHC, 2022-04-01 10:05:20

How to create a product filter in React?

There are React

Main.jsx components

import React from "react";
import { Products } from "../Products";
import { Filter } from "../Filter";
import { Product } from "../Product";

class Main extends React.Component {
  state = {
    products: [],
  };

  componentDidMount() {
    fetch("./products.json")
      .then((responce) => responce.json())
      .then((data) => this.setState({ products: Object.values(data) }));
  }

  productFilter = (type = "all") => {
    const selected = [];
    return this.state.products.map((product) => {
      if (product.prod_status.contains(type)) {
        selected.push(product);
      }
    });
  };

  render() {
    const { products } = this.state;

    return (
      <main className="container content">
        <Filter />
        <Products products={products} />
      </main>
    );
  }
}

export { Main };


Filter.jsx

import React from "react";

class Filter extends React.Component {
  state = {
    type: "all",
  };

  hadleFilter = (event) => {
    this.setState({ type: event.target.dataset.type }, () => {
      this.props.productFilter(this.state.type);
    });
  };

  render() {
    return (
      <div clasName="row">
        <div className="sort_container">
          <h3 className="sort_title">Sortować według:</h3>
          <label>
            <input
              className="with-gap"
              name="prod-status"
              type="radio"
              data-type="all"
              onChange={this.hadleFilter}
              checked={this.state.type === "all"}
            />
            <span>All</span>
          </label>
          <label>
            <input
              className="with-gap"
              name="prod-status"
              type="radio"
              data-type="recommended"
              onChange={this.hadleFilter}
              checked={this.state.type === "recommended"}
            />
            <span>Recommended</span>
          </label>
          <label>
            <input
              className="with-gap"
              name="prod-status"
              type="radio"
              data-type="saleout"
              onChange={this.hadleFilter}
              checked={this.state.type === "saleout"}
            />
            <span>Saleout</span>
          </label>
          <label>
            <input
              className="with-gap"
              name="prod-status"
              type="radio"
              data-type="bestseller"
              onChange={this.hadleFilter}
              checked={this.state.type === "bestseller"}
            />
            <span>Bestseller</span>
          </label>
          <label>
            <input
              className="with-gap"
              name="prod-status"
              type="radio"
              data-type="promotion"
              onChange={this.hadleFilter}
              checked={this.state.type === "promotion"}
            />
            <span>Rromotion</span>
          </label>
          <label>
            <input
              className="with-gap"
              name="prod-status"
              type="radio"
              data-type="new"
              onChange={this.hadleFilter}
              checked={this.state.type === "new"}
            />
            <span>New</span>
          </label>
        </div>
      </div>
    );
  }
}

export { Filter };


Link to the entire repository - here

Question - I tried to make the productFilter () function in Main.jsx, which I pass to Filter.jsx to implement the filter after clicking on any radio. It's clear that the function is not written correctly, please help me fix the errors and bring the filter to working condition

Answer the question

In order to leave comments, you need to log in

3 answer(s)
0
0xD34F, 2022-04-01
@JekaHC

In addition to the full data, store the filtered ones as well. Display them. Let the filter value be stored in the parent - pass it to the filter component instance along with the function that will update it (the value). When you update the filter value, you update the array of filtered data.

const Filter = ({ title, values, value, onChange }) => (
  <div>
    <h3>{title}</h3>
    {values.map(n => (
      <label>
        <input
          type="radio"
          onChange={() => onChange(n)}
          checked={value === n}
        />
        {n}
      </label>
    ))}
  </div>
);

state = {
  ...
  filteredProducts: [],
  status: 'all',
}

onFilterStatusChange = status => {
  this.setState({ status });
}

filterProducts() {
  this.setState(({ status }) => ({
    filteredProducts: status === 'all'
      ? this.state.products
      : this.state.products.filter(n => n.prod_status.includes(status)),
  }));
}

componentDidUpdate(prevProps, prevState) {
  if (this.state.status !== prevState.status) {
    this.filterProducts();
  }
}

render() {
  ...
    <Filter
      title="Status:"
      values={[ 'all', 'recommended', 'saleout', 'bestseller', 'new' ]}
      value={this.state.status}
      onChange={this.onFilterStatusChange}
    />
    <Products products={this.state.filteredProducts} />
  ...
}

L
low molecular macro, 2022-04-01
@molekulyarniy

return this.state.products.map((product) => {
try forEachinsteadmap

A
Alexander, 2022-04-01
@Aleksandr-JS-Developer

productFilter = (type = "all") => {
    const selected = [];
    return this.state.products.map((product) => {
      if (product.prod_status.contains(type)) {
        selected.push(product);
      }
    });
  };

You don’t return anything in the map loop, but add it to selected. But you return the result of map operation, i.e. an empty array (more precisely, filled with only undefined).
+ Arrow as class method??
+ Read about this, classes and ... array methods or something...
Try this:
productFilter = function (t = "all") {
  return this.state.products.filter((p) => p.prod_status.contains(t));
};

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question