Skip to main content
The favorites feature lets users bookmark any cryptocurrency from the listing table. Favorited coins are stored in localStorage so they survive page refreshes and browser restarts. The /favs route shows a dedicated view with only the favorited coins and an individual price chart for each one.

How to add a favorite

Every CryptoCard row includes a star icon button in the rightmost column. Clicking it toggles the coin’s favorited state:
  • Empty star — the coin is not favorited
  • Yellow filled star — the coin is favorited
The toggle is instant and requires no confirmation.

useFavorites hook

Favorites state is managed by the useFavorites hook in src/hooks/useFavorites.jsx. The hook initializes from localStorage on first render and writes back to localStorage any time the list changes:
useFavorites.jsx
import { useState, useEffect } from "react";

export function useFavorites() {
  const [favorites, setFavorites] = useState(() => {
    try {
      const savedFavorites = localStorage.getItem("cryptoFavorites");
      return savedFavorites ? JSON.parse(savedFavorites) : [];
    } catch {
      return [];
    }
  });

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

  const addFavorite = (cryptoId) => {
    setFavorites((prev) => [...prev, cryptoId]);
  };

  const removeFavorite = (cryptoId) => {
    setFavorites((prev) => prev.filter((id) => id !== cryptoId));
  };

  const isFavorite = (cryptoId) => {
    return favorites.includes(cryptoId);
  };

  return { favorites, addFavorite, removeFavorite, isFavorite };
}

Returned values

favorites
string[]
Array of CoinGecko coin IDs that are currently favorited (e.g. ["bitcoin", "solana"]).
addFavorite
(cryptoId: string) => void
Appends a coin ID to the favorites list and persists it to localStorage.
removeFavorite
(cryptoId: string) => void
Removes a coin ID from the favorites list and updates localStorage.
isFavorite
(cryptoId: string) => boolean
Returns true if the given coin ID is in the favorites list.

localStorage persistence

Favorites are stored under the key "cryptoFavorites" as a JSON-serialized array of coin ID strings:
["bitcoin", "ethereum", "solana"]
The lazy initializer in useState reads from localStorage synchronously on mount, so the favorites list is always populated before the first render. If localStorage is unavailable or the stored value is corrupted the hook silently falls back to an empty array.
Favorites are scoped to the browser. They are not synced across devices or user accounts.

Favorites page (/favs)

The Favorites page at /favs loads the full top-20 coin data via keepInfo() and then filters it down to only the favorited coins:
favorites.jsx
useEffect(() => {
  async function loadCryptos() {
    const data = await keepInfo();
    setFavoriteCryptos(
      data.filter((crypto) => favorites.includes(crypto.id))
    );
  }
  loadCryptos();
}, [favorites]);
The page re-runs this filter whenever the favorites array changes, so adding or removing a favorite from the listing page is reflected immediately if the user is already on /favs. For each favorited coin the page renders:
  1. A CryptoCard row in the same table format as the home page
  2. An AreaChartFillByValue chart locked to that coin’s ID, showing its price history
If no coins have been favorited yet, the page shows a prompt directing the user to add some from the market listing.

Build docs developers (and LLMs) love