On button click I'am adding product information to local storage and setting it to context.
I'm using context in two places - header and products page, syntax is almost the same. There is a console.log in header and whenever i'am interacting with context it's instantly firing, confirming that context is working fine. However, when i enter products page i need to reload it one more time in order to get the data. Why is that?
Context file
import React, { useState, useEffect } from "react";
export const LikedContext = React.createContext([{}, () => {}]);
export const LikedProvider = (props) => {
const [liked, setLiked] = useState(null);
useEffect(() => {
if (typeof window !== "undefined") {
let likedData = localStorage.getItem("liked");
likedData = likedData ? JSON.parse(likedData) : "";
setLiked(likedData);
}
}, []);
return (
<LikedContext.Provider value={[liked, setLiked]}>
{props.children}
</LikedContext.Provider>
);
};
Header
export const LikedProductsIcon = () => {
const [liked, setLiked] = useContext(LikedContext);
console.log("liked header", liked);
const likedCount =
null !== liked && Object.keys(liked).length ? liked.totalProductsCount : "";
const totalPrice =
null !== liked && Object.keys(liked).length ? liked.totalProductsPrice : "";
return (
<>
<CartContainer to="/pamegti-produktai">
<CountCircle>
<HeartSvg />
{likedCount ? <span>{likedCount}</span> : ""}
</CountCircle>
</CartContainer>
</>
);
};
Liked products page
const LikedProducts = () => {
const [liked, setLiked] = useContext(LikedContext);
console.log("liked page", liked);
return (
<Layout>
<Container>
{liked ? (
liked.products.map((product, index) => (
<ProductsCard product={product} blackText />
))
) : (
<div>Pamėgtų produktų nėra.</div>
)}
</Container>
</Layout>
);
};
CodePudding user response:
If you render multiple <LikedProviders>
, then they will each have their own independent state. Setting state in one of them will not affect the other one. The reason they sync up when you refresh the page is that they both load from local storage and see the same value. But that only happens on load, and they will get out of sync after that.
If you want the state to be shared, then you want to just render one of them. Place it at the top of your component tree (app.js is a good spot) so that it's accessible by all the components that need it, and delete the other one.