Filtering categories with react hooks

Viewed 817

I am learning React and sometimes I write too much lines of code and I would like to see how other people would resolve this in a better way.

I have created the landing page of an academy, listing the courses that they provide with all the stuff that is related to them. This is the code

  const [courses, setCourses] = useState([]);

  useState(() => {
    axios
      .get("db.json")
      .then((response) => {
        setCourses(response.data.courses);
      })
      .catch((error) => {
        console.log(error);
      });
  }, []);

  return (
    <div className="container">
      <div className="course-header">
        <h1>Course List</h1>
// here I want to display some categories //
      </div>
      {courses.map((course) => (
        <div data-cy={"course-" + course.id} key={course.id}>
          <h2> {course.title}</h2>
          <div> {course.description}</div>
          <br />
          <div>
            <h4>Category:</h4>
            {course.category}
          </div>
          <br />
          <div>
            <h4>Instructors:</h4> {course.instructors}
          </div>
          <br />
          <div> {course.info}</div>
          <br />
          <div>
            <h4>Price:</h4> {course.price}
          </div>
          <br />
        </div>
      ))}
    </div>
  );
};

Fair enough, now we have the information every time we render, but now I would like to display different categories next to the title, and once you click in one of them, I want to only display the courses related to that category. It was my idea that I should use an useEffect with an onClick event, but, can I do the same only using the same useState that I already have?

By the way, my json looks like this:

{
  "courses": [
    {
      "title": "",
      "slug": "",
      "category": "",
      "dates": [],
      "price": "",
      "active": true,
      "description": "",
      "info": "",
      "instructors": ""
    },
}
1 Answers

To do so, you need to store the category clicked and then filter your courses array to only display the courses which have this category with the following code :

import _ from "lodash";

const [courses, setCourses] = useState([]);
const [filteredCourses, setFilteredCourses] = useState([]);

useState(() => {
    axios
      .get("db.json")
      .then((response) => {
        setCourses(response.data.courses);
        setFilteredCourses(response.data.courses);
        setCategories(_.uniqBy(response.data.courses.map(course => 
        course.category), 'category');
      })
      .catch((error) => {
        console.log(error);
      });
  }, []);
{filteredCourses.map((course) => (
<div data-cy={"course-" + course.id} key={course.id}>
  <h2> {course.title}</h2>
  {categories.map(category => (
    <button onClick={() => onClickButton(category)}>{category}</button>
  )}
  ...
// this function is executed when you click on the button you mentioned
// chosenCategory below is the category clicked
const onClickButton = (chosenCategory) => {
  setFilteredCourses(courses.filter(course => course.category === chosenCategory)
}

Filter method : https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter

Uniq by method from lodash : https://www.geeksforgeeks.org/lodash-_-uniqby-method/

Related