I am making an app for bookmarking characters. I have to store Bookmarked characters in local Storage so when I refresh the page I can see my bookmarked elements.
My elements are saving correctly into local storage but when I refresh the page the state of bookmarked icon is not saved (It is put back on unfilled icon although elements are still in local storage)
The second problem is that I don't know how to implement removing bookmarked elements from local storage. I want to un-bookmark specific element and remove that element from local storage. You can see in my handleBookmarking function how I did bookmarking but I don't know how to do two-way function for bookmarking and -unbookmarking. Any ideas maybe?
Here is the code:
CharactersList.js
import React, { useState } from "react";
import "./CharactersList.css";
import { RiBookmarkLine } from "react-icons/ri";
import { RiBookmarkFill } from "react-icons/ri";
const CharactersList = (props) => {
const [isLiked, setIsLiked] = useState([]);
const [favourites, setFavourites] = useState([]);
const saveToLocalStorage = (data) => {
localStorage.setItem("react-bookmarked-characters", JSON.stringify(data));
};
const handleBookmarking = (character) => {
if (isLiked.includes(character.id)) {
const newIsLiked = [...isLiked];
setIsLiked(newIsLiked);
} else {
setIsLiked([...isLiked, character.id]);
const newBookmarkedList = [...favourites, character];
setFavourites(newBookmarkedList);
saveToLocalStorage(newBookmarkedList);
}
};
const Bookmarked = ({ id }) => {
return isLiked.includes(id) ? <RiBookmarkFill /> : <RiBookmarkLine />;
};
return (
<>
{props.characters.map((character, index) => (
<div className="card-container" key={index}>
<img
src={`${character.thumbnail.path}/standard_fantastic.${character.thumbnail.extension}`}
alt="character"
className="image"
/>
<div className="info-container">
<p className="name">{character.name}</p>
<div
className="icon"
onClick={() => {
handleBookmarking(character);
}}
>
<Bookmarked id={character.id} />
</div>
</div>
</div>
))}
</>
);
};
export default CharactersList;
App.js So in the app.js I am calling two lists of characters, one is when the search input is empty (shows all bookmarked elements) and the second one is on search (shows all elements).
const App = () => {
const [characters, setCharacters] = useState([]);
const [search, setSearch] = useState("");
const [favourites, setFavourites] = useState([]);
const [currentPage, setCurrentPage] = useState(1);
const [characterPerPage] = useState(20);
const getCharactersRequest = async () => {
const url = `https://gateway.marvel.com/v1/public/characters?nameStartsWith=${search}&ts=1&apikey=&hash=`;
const response = await fetch(url);
const responseJSON = await response.json();
if (responseJSON.data) {
setCharacters(responseJSON.data.results);
}
};
useEffect(() => {
getCharactersRequest(search);
}, [search]);
useEffect(() => {
const bookMarkedData = JSON.parse(
localStorage.getItem("react-bookmarked-characters")
);
if (bookMarkedData) {
setFavourites(bookMarkedData);
}
}, [search]);
// Get 20 posts
const indexOfLastCharacter = currentPage * characterPerPage;
const indexOfFirstCharacter = indexOfLastCharacter - characterPerPage;
const slicedFavourites = favourites.slice(
indexOfFirstCharacter,
indexOfLastCharacter
);
return (
<div>
<div className="heading-container">
<SearchBarHeading heading={"MARVEL CHARACTERS"} />
<SearchBar search={search} setSearch={setSearch} />
</div>
<div className="cards-container">
{search === "" ? (
<CharactersList characters={slicedFavourites} />
) : (
<CharactersList characters={characters} />
)}
</div>
</div>
);
};
export default App;