Command Palette

Search for a command to run...

Hectal
Phase 12: TypeScript with React
React · Exercise 5 of 5 Previous
Advanced

Favourites: typed context, a guard hook and a generic list

Build a small favourites app with the patterns from this phase. The starter has two copy-pasted list components and stars that do nothing.

Context: create FavouritesContext with createContext<FavouritesValue | null>(null), where FavouritesValue has ids: string[] and toggle: (id: string) => void. A FavouritesProvider holds the ids in state. A guard hook useFavourites() throws an Error when there is no provider and otherwise returns the value.

Generic list: replace BookList and FilmList with one function List<T> taking items: T[], getId: (item: T) => string and renderLabel: (item: T) => ReactNode. Each <li> shows the label and a <button className="star"> with ★ when the item is a favourite and ☆ when not (also set aria-pressed). Clicking it toggles the favourite.

Keep the ids: the lists are <ul id="books"> and <ul id="films">, and <p id="fav-count"> shows Favourites: <number>.

What Check tests

  1. Both lists render with a star per item
  2. Starring a book fills its star and counts it
  3. Starring a film adds to the same count
  4. Clicking a filled star removes it, and aria-pressed follows
  5. Context has a null default and a guard hook that throws
  6. One generic List<T> replaces the two list components

Stuck? One hint at a time

The solution unlocks after your first Check. Try first: that is where the learning happens.

Runs in your browser. Your code is saved here.

Your page

Press Run to see the page.

Console

Nothing logged yet.