0

I am trying to create an app where the user can click on a category and it will set the displayWork array to the value of the category and thus display the items in that array.
I have all of the work stored in an array

 const [workList, setWorkList] = useState([
    { title: "aaa", image: "./images/1.jfif", type: "landscaping" },
    { title: "plumbing", image: "./images/2.jfif", type: "plumbing" },
    { title: "Other 3", image: "./images/3.png", type: "other3" },
    { title: "Other 4", image: "./images/3.png", type: "other4" },
  ]);

and then I have my displayWork mapped to the page, I plan on changing it through using array.filter()

let filteredWork = workList.filter(function (work) {
      return work.type === catagory;
    });

then I have a row of categories like this to set the parameters of the filter

 <div className="col-sm-2  workCatagory" onClick={() => setCatagory("landscaping")}>
          Land Scaping
        </div>
        <div className="col-sm-2 workCatagory" onClick={() => setCatagory("plumbing")}>
          plumbing
        </div>
        <div className="col-sm-2 workCatagory" onClick={() => setCatagory("other3")}>
          test3
        </div>
        <div className="col-sm-2 workCatagory" onClick={() => setCatagory("other4")}>
          Test4
        </div>

And then I am setting the displayWork to the value of the filtered array like so:

 <div className="row workBars" onClick={() => handleClick()}>
 const handleClick = () => {
setDisplayWork(filteredWork)
 }

The problem with this approach is the change is not reflected immediately upon clicking the button. Using this solution here I was able to fix this

useEffect(() => {
      handleClick()
    }, [handleClick])

But I ran into an error message and the page crashing on me very often, I cannot get the state to update immediately without also creating an infinite loop. A link to my full page is here github I appreciate any advice you may have

imstupidpleasehelp
  • 1,618
  • 2
  • 16
  • 36

2 Answers2

1

Because you use non-state variables to dependencies. So you need to wrap it into useMemo, useCallback to avoid infinitive loop

const filteredWork = useMemo(
  () =>
    workList.filter(function (work) {
      return work.type === catagory;
    }),
  [workList, category],
);

const handleClick = useCallback(() => {
  setDisplayWork(filteredWork);
}, [setDisplayWork, filteredWork]);
Viet
  • 12,133
  • 2
  • 15
  • 21
0

I just changed the architecture of the component.

Instead of calling two functions (setCategory and handleClick) for a single action is not a good idea.

So I added an useEffect hook, which gets triggered whenever the category is changed. In this way, the whole execution will be somehow synchronous.

import React, { useState, useEffect } from "react";
import { gsap } from "gsap";

import { ScrollTrigger } from "gsap/ScrollTrigger";
export const Work = () => {
  gsap.registerPlugin(ScrollTrigger);
  const [workList, setWorkList] = useState([
    { title: "aaa", image: "./images/1.jfif", type: "landscaping" },
    { title: "aaa", image: "./images/1.jfif", type: "landscaping" },
    { title: "aaa", image: "./images/1.jfif", type: "landscaping" },
    { title: "aaa", image: "./images/1.jfif", type: "landscaping" },
    { title: "aaa", image: "./images/1.jfif", type: "landscaping" },
    { title: "aaa", image: "./images/1.jfif", type: "landscaping" },

    { title: "plumbing", image: "./images/2.jfif", type: "plumbing" },
    { title: "plumbing", image: "./images/2.jfif", type: "plumbing" },
    { title: "plumbing", image: "./images/2.jfif", type: "plumbing" },
    { title: "plumbing", image: "./images/2.jfif", type: "plumbing" },
    { title: "plumbing", image: "./images/2.jfif", type: "plumbing" },
    { title: "plumbing", image: "./images/2.jfif", type: "plumbing" },
    { title: "plumbing", image: "./images/2.jfif", type: "plumbing" },
    { title: "plumbing", image: "./images/2.jfif", type: "plumbing" },

    { title: "Other 3", image: "./images/3.png", type: "other3" },
    { title: "Other 4", image: "./images/3.png", type: "other4" },
  ]);
  const [displayWork, setDisplayWork] = useState([
    { title: "aaa", image: "./images/test.png", type: "landscaping" },
    { title: "aaa", image: "./images/test.png", type: "landscaping" },
    { title: "aaa", image: "./images/test.png", type: "landscaping" },
    { title: "aaa", image: "./images/test.png", type: "landscaping" },
    { title: "aaa", image: "./images/test.png", type: "landscaping" },
  ]);
  const [catagory, setCatagory] = useState("Select a catagory");

  
    //let newArray = workList.filter(workList.type.includes(catagory))
  
    
  
const Animation = () => {
console.log('woo')
}

  useEffect(() => {
    let filteredWork = workList.filter(function (work) {
      return work.type === catagory;
    });
    setDisplayWork(filteredWork);
  }, [catagory, workList]);
  

  return (
    <div className="workPage" id="workPage">
      <h1 className="text-center">Here's what we can do</h1>
      <div className="row workBars">
        <div className="col-sm-2"></div>
        <div className="col-sm-2  workCatagory" onClick={() => setCatagory("landscaping")}>
          Land Scaping
        </div>
        <div className="col-sm-2 workCatagory" onClick={() => setCatagory("plumbing")}>
          plumbing
        </div>
        <div className="col-sm-2 workCatagory" onClick={() => setCatagory("other3")}>
          test3
        </div>
        <div className="col-sm-2 workCatagory" onClick={() => setCatagory("other4")}>
          Test4
        </div>
      </div>
      <h1> {catagory}</h1>
      <div className="row">
        <div className="col-sm-2"></div>
        {displayWork.map((displayWork) => (
          <div className="col-sm-4">
            {" "}
            <br />
            <p>{displayWork.title}</p>
            <img
              src={displayWork.image}
              alt={displayWork.name}
              className="img-fluid workImage"
            ></img>
          </div>
        ))}
        <div className="col-sm-2"></div>
      </div>
    </div>
  );
};

DJ Hemath
  • 632
  • 6
  • 18