Conditional rendering of useContext

943 views Asked by At

The task requires me to fetch data from an API, based on target category groups.

For example, www.localhost:8000/women fetches all data corresponding to women, and www.localhost:8000/women fetch all data corresponding to men.

I have now created a common ContextProvider where data is fetched based on a value.

Please find the code below for better clarity.

export const ProductCategoryContext = createContext();

const ProductCategoryContextProvider = ({ children }) => {
  const [products, setProducts] = useState([]);

//conditional value which must be updated in onClick function of a <Link>.
  const [targetGroup, setTargetGroup] = useState("");

  const URL = `${process.env.REACT_APP_HOST}`;

  async function getproducts() {
    console.log(targetGroup);
    console.log(123);
    try {
      if (targetGroup === "women") {
        const womensData = await fetch(`${URL}/women`);
        const jsonData = await womensData.json();
        console.log(jsonData?.items);
        setProducts(jsonData?.items);
      } else if (targetGroup === "men") {
        console.log(targetGroup);
        const mensData = await fetch(`${URL}/men`);
        const jsonData = await mensData.json();
        console.log(jsonData?.items);
        setProducts(jsonData?.items);
      }
    } catch (error) {
      console.error(error);
    }
  }

  useEffect(() => {
    getproducts();
  }, []);

  return (
    <ProductCategoryContext.Provider
      value={{
        product: products,
        targetGroup: targetGroup,
        setTargetGroup: setTargetGroup,
      }}
    >
      {children}
    </ProductCategoryContext.Provider>
  );
};

The code for the event handler is as below:

  const { setTargetGroup } = useContext(ProductCategoryContext);

 return (<Link
          onClick={() =>  setTargetGroup("women")}
          className="category-links"
          to="/create/women"
        >
          <div className="card">
            <div className="card_image">
              <img
                className="category-images"
                src={require("../../assets/images/women-tile-image.jpg")}
                alt="image for womens section"
              />
            </div>
          </div>
        </Link>)

Now, the value of targetGroup remained unupdated because of which I am unable to fetch the data. I'm confused about what the problem could be?

1

There are 1 answers

1
Drew Reese On BEST ANSWER

From what I can see, the useEffect hook is missing a dependency on the referenced targetGroup state value. The empty dependency array tells React to run the effect once on the initial render. Since the targetGroup initial state value is "" nothing is fetched and then the effect isn't "listening" for any dependency to change to possibly refetch.

Add targetGroup to the useEffect hook's dependency array so when it updates the effect callback is triggered. Move URL and getproducts into the useEffect callback body to remove them as dependencies.

const ProductCategoryContextProvider = ({ children }) => {
  const [products, setProducts] = useState([]);

  //conditional value which must be updated in onClick function of a <Link>.
  const [targetGroup, setTargetGroup] = useState("");

  useEffect(() => {
    const URL = `${process.env.REACT_APP_HOST}`;

    async function getproducts() {
      try {
        if (targetGroup === "women") {
          const womensData = await fetch(`${URL}/women`);
          const jsonData = await womensData.json();
          setProducts(jsonData?.items);
        } else if (targetGroup === "men") {
          const mensData = await fetch(`${URL}/men`);
          const jsonData = await mensData.json();
          setProducts(jsonData?.items);
        }
      } catch (error) {
        console.error(error);
      }
    };

    getproducts();
  }, [targetGroup]); // <-- add targetGroup as dependency

  return (
    <ProductCategoryContext.Provider
      value={{
        product: products,
        targetGroup: targetGroup,
        setTargetGroup: setTargetGroup,
      }}
    >
      {children}
    </ProductCategoryContext.Provider>
  );
};

You may also find adding the ESLint plugin for React hooks helpful. It will help you with missing dependencies and other general React hook issues.