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?
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.