Exercise 20
Work with Component Libraries
Learn the landscape of UI libraries vs design systems, use Shadcn components to build a dynamic city list with forms, useEffect, and localStorage.
What you'll learn
Key takeaways from this exercise
- Understanding the landscape of UI libraries and how they relate to each other
- Understanding the difference between component libraries and design systems
- Replacing a custom component with a Shadcn library component
- Creating a structured data file as a refresher on JSON
- Building a form with a dialog, combobox, and
useEffectto manage a dynamic city list in local storage
Introduction
In practice, almost nobody builds every UI element from scratch. Buttons, dialogs, dropdowns, accordions, form inputs — these are common patterns that have been solved thousands of times. Instead of reinventing them, most teams use a component library: a collection of pre-built, configurable UI components that handle the complex parts (accessibility, keyboard navigation, focus management) so you can focus on your product's unique interface.
UI libraries
There are many UI libraries to choose from. Here are a few notable ones:
- Base UI — an unstyled component library from the creators of Radix, Floating UI, and Material UI. It provides accessible, composable primitives without imposing any visual opinions.
- Radix UI — a headless library that provides component behavior (keyboard navigation, focus management, accessibility) without any default styling. You get the logic; you bring the visuals.
- Shadcn UI — a popular library built on top of Radix and Base primitives. Highly customizable and very easy to use with AI, which is part of why it has become so popular recently.
Shadcn is what we'll use in this exercise. When you add a component, it creates a real file in your components/ui/ folder. Most components come with variants — different visual options exposed through props. A Button might have variants like default, secondary, outline, ghost. Because you own the source, there are no limitations on what you can change.
Component libraries vs design systems
It's important not to confuse component libraries with design systems. They are related but fundamentally different things.
Component libraries like Base UI, Radix, or Shadcn are tools. They are unopinionated, flexible, and designed to be adapted to any product. They don't tell you what your app should look like — they give you building blocks.
Design systems are opinionated. They are built for a specific platform, product, or ecosystem, and they come with strong visual and interaction opinions. Examples include Carbon (IBM), Material Design (Google) or Fluent (Microsoft). Many of these are open source, meaning you can technically use them to build anything. However, using Carbon for a non-IBM product could create unintended brand confusion — users might associate your app with IBM even though it has nothing to do with it. Design systems carry identity. Component libraries don't.
Shadcn sits in an interesting spot. It uses CSS variables as design tokens — colors, spacing, typography — defined in one place and referenced by every component. Change a token and it propagates across the entire app. This gives you design system capabilities without locking you into someone else's design choices.
useEffect and forms
Alongside UI libraries, this exercise introduces two more concepts you'll encounter constantly in React codebases.
The first is useEffect — another React hook, like useState. While useState holds data that can change, useEffect runs code in response to those changes. For example, loading saved preferences from local storage when a page first opens, or syncing data whenever a list gets updated. You'll see it used in this exercise to persist and retrieve the user's city list.
The second is forms. It's hard to design or prototype anything useful without touching them — forms are the primary way users provide structured information to your app that can't be achieved with just a click of a button. Think of search inputs, login screens, settings panels, or any place where a user types, selects, or submits data. In React, form inputs are often controlled — their value is bound to state, so the component has full control over what the user sees and types. You'll build a form with a search input and a submit button in this exercise.
Create a free account to access the full course
In order to access full course content and track your progress, please sign in