In Next.js I'm using this code:
const [card, setcard] = useState([]);
useEffect(() => {
localStorage.setItem('items', JSON.stringify(card));
}, [card]);
useEffect(() => {
const items = JSON.parse(localStorage.getItem('items'));
if (items) {
setcard(items);
}
}, []);
I can see that when the value of the card changes, the local storage shows me the value of the card, which is a JSON, so when I refresh, I just see this []
I used this tutorial: https://www.freecodecamp.org/news/how-to-use-localstorage-with-react-hooks-to-set-and-get-items/
How can I fix the code so I don't lose the value of the card after a refresh?
Also, I was using cookies
to store the card
like this, and it was working, but when the items in my JSON got larger, the cookie didn't store anymore; that's why I want to use local storage.
Example:
const [card, setcard] = useState(() => eval(getCookie('card') || []));
setCookie('card', JSON.stringify(card), {
path: '/',
maxAge: 60 * 60 * 24,
HttpOnly: true,
Secure: true,
});
The issue is that your first useEffect
(with the dependency array [card]
) gets triggered before your useEffect
hook without any dependency array. You could probably fix it by reversing the order of them, but I would be more thorough than that and only have the one with the [card]
dependency array do the save if it sees something other than the default []
that you're supplying. Here's a way to do that:
// Outside the component
const defaultCard = [];
function YourComponent() {
const [card, setCard] = useState(defaultCard);
useEffect(() => {
const items = JSON.parse(localStorage.getItem("items"));
if (items) {
setCard(items);
}
}, []);
useEffect(() => {
if (card !== defaultCard) { // Note we're checking *object identity* here
localStorage.setItem("items", JSON.stringify(card));
}
}, [card]);
// ...
}
Using object identity makes it so that the code will never save the specific empty array we used as a default (but will store an empty array resulting from the user removing all the cards on purpose).
Alternatively, don't rely on an effect to save the array. Instead, have a wrapper for setCard
:
function YourComponent() {
const [card, setCardWorker] = useState(defaultCard);
const setCard = useCallback(
(card) => {
localStorage.setItem("items", JSON.stringify(card));
setCardWorker(card);
},
[setCardWorker]
);
useEffect(() => {
const items = JSON.parse(localStorage.getItem("items"));
if (items) {
setCard(items);
}
}, []);
// ...code using `setCard` to update `card` as things are added and removed...
}
(I've used setCard
rather than setcard
in these because the vastly common standard is to capitalize the noun after set
in these things rather than use all lower-case.