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

3
  • A stackblitz or codesandbox would help us to solve it easily. Commented Aug 2, 2021 at 2:48
  • Here you are codesandbox.io/s/admiring-khayyam-fjktw?file=/src/pages/work.js Commented Aug 2, 2021 at 2:53
  • I wonder what do you mean by "the change is not reflected immediately upon clicking the button". Maybe there is a different solution. Commented Aug 2, 2021 at 3:02

2 Answers 2

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]);
Sign up to request clarification or add additional context in comments.

5 Comments

TypeError: Object(...) is not a function Do you know why it's giving me this error?
> 53 | const handleClick = useCallBack(() => {
Where do you import useCallback?
It looks like I just had a typo, this is working now. Thank you, I will study these 2 hooks so i can learn in the future.
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>
  );
};

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.