Search code examples
javascriptreactjsuse-state

LocalStorage keeps changing my key-pair instead of pushing to the array


I want to add to the array a new object everytime I click at a card, but when I do so it changes the last key-pair to the new one and it doesnt add it. I chose this method of updating the state since I saw it is more popular than the one with the push.

import React, { useState, useEffect } from "react";
import { Link } from "react-router-dom";
import { AiOutlineHeart, AiFillHeart } from "react-icons/ai";

import styles from "./MovieCard.module.css";

const imagePrefixUrl = "http://image.tmdb.org/t/p/w500";

const MovieCard = (props) => {
const [items, setItems] = useState(
 JSON.parse(localStorage.getItem("favorites")) || []
);
const [liked, setLiked] = useState(false);
const movie = props?.movie;

const addFavoriteHandler = (movie) => {
 setItems((data) => [...data, movie]);
};

useEffect(() => {
 localStorage.setItem("favorites", JSON.stringify(items));
}, [items]);

return (
 <div className={styles.container}>
   {liked ? (
     <button className={styles.heartIcon} onClick={() => setLiked(false)}>
       <AiFillHeart />
     </button>
   ) : (
     <button
       className={styles.heartIcon}
       onClick={() => addFavoriteHandler(movie)}
     >
       <AiOutlineHeart />
     </button>
   )}
   <Link to={`/movie/${movie.id}`} title={movie?.title}>
     <img src={`${imagePrefixUrl}${movie?.backdrop_path}`} />
     <p>{movie?.title}</p>
   </Link>
 </div>
);
};

export default MovieCard;

Solution

  • I am assuming from the component name MovieCard, that your app would have multiple instances of this component under a parent component (assumed to be MovieCardList). A solution to your issue would be to lift the state and addFavoriteHandler

    const [items, setItems] = useState(
     JSON.parse(localStorage.getItem("favorites")) || []
    );
    

    to the parent component MovieCardList and pass the handler addFavoriteHandler as a prop to each MovieCard. This would ensure that you have a single point for updating your localStorage key favorites and it would not be overridden by new update.

    The reason for the override issue you are experiencing is that each card has an instance of items and it does not fetch the latest value of favorites from the localStorage before updating it, meaning it would always override the favorites in localStorage as per the current code.