Design Patterns in React

5 questions found

What is the container and presentational component pattern in React?

Intermediate
This pattern separates a component into two parts. The container component handles data fetching and logic, while the presentational component only receives data through props and focuses purely on how things look. This makes the presentational part easy to reuse and test on its own.
function UserListContainer() {
  const { data: users, loading } = useFetch('/api/users');
  return <UserList users={users} loading={loading} />;
}

function UserList({ users, loading }) {
  if (loading) return <p>Loading</p>;
  return <ul>{users.map((u) => <li key={u.id}>{u.name}</li>)}</ul>;
}
Real-world example A team separates their user page into a container that fetches data from the server and a presentational component that simply displays the list, making the presentational part reusable on a different page that gets its data differently.

Common follow-ups: Has this pattern become less common since hooks were introduced, and why?;How would you test the presentational component on its own without needing real data?

Custom Hooks;Component Composition & Children Props

What is the compound component pattern in React, and when is it useful?

Advanced
Compound components let several related components work together and share hidden state behind the scenes, while still letting the person using them arrange the pieces however they like. A common example is a set of Tabs and Tab components that automatically know which tab is currently active without the parent needing to manage that manually.
function Tabs({ children }) {
  const [activeIndex, setActiveIndex] = useState(0);
  return React.Children.map(children, (child, index) =>
    React.cloneElement(child, { isActive: index === activeIndex, onSelect: () => setActiveIndex(index) })
  );
}

function Tab({ label, isActive, onSelect }) {
  return <button onClick={onSelect} style={{ fontWeight: isActive ? 'bold' : 'normal' }}>{label}</button>;
}
Real-world example A component library builds a Tabs and Tab set using the compound component pattern, letting developers freely arrange and style each tab however they want, while the tabs still correctly share which one is currently selected.

Common follow-ups: How does the newer Context based approach improve on the older cloneElement based approach for compound components?;What are some other common examples of compound components in popular libraries?

Context API;Component Composition & Children Props

What is the controlled component pattern and why is it considered a best practice for forms?

Intermediate
In a controlled component, the form input's value is always driven by React state, meaning React is the single source of truth for what the input shows. This makes it easy to validate, format, or react to changes immediately, since every keystroke updates the component's own state right away.
function EmailInput() {
  const [email, setEmail] = useState('');
  return (
    <input
      value={email}
      onChange={(e) => setEmail(e.target.value.toLowerCase())}
    />
  );
}
Real-world example A signup form automatically converts every email address a user types into lowercase letters as they type, since the input's value is fully controlled by React state that can be transformed on every keystroke.

Common follow-ups: What is the alternative uncontrolled component pattern, and when might it be simpler to use instead?;What happens if you set an input's value without also providing an onChange handler?

Forms: Controlled & Uncontrolled Components;Props & State

What is the provider pattern in React and how does it relate to the Context API?

Advanced
The provider pattern wraps a piece of your app in a component that supplies shared data and functions to everything inside it, usually built using the Context API. This keeps related state and logic organized in one place, and any component nested inside the provider can access it without prop drilling.
function AuthProvider({ children }) {
  const [user, setUser] = useState(null);
  const login = (userData) => setUser(userData);
  const logout = () => setUser(null);
  return (
    <AuthContext.Provider value={{ user, login, logout }}>
      {children}
    </AuthContext.Provider>
  );
}
Real-world example An app wraps its entire component tree in an AuthProvider, giving every page easy access to the current user, plus login and logout functions, without passing any of that data manually through props.

Common follow-ups: How is the provider pattern different from just using props to pass data down?;When would you use multiple providers together, like both an AuthProvider and a ThemeProvider?

Context API;State Management

What is the single responsibility principle and how does it apply to writing React components?

Beginner
The single responsibility principle means each component should do just one clear thing, such as displaying a single piece of information or handling one specific interaction. Breaking a large component into smaller, focused ones makes the code easier to read, test, and reuse in other places.
// One big component doing too many things
function UserPage() { /* fetches data, shows profile, shows posts, shows settings */ }

// Split into smaller, focused components
function UserPage() {
  return (
    <>
      <UserProfile />
      <UserPosts />
      <UserSettings />
    </>
  );
}
Real-world example A team breaks apart one giant three hundred line UserPage component into three smaller, focused components, each handling just one job, making the code much easier for new team members to understand.

Common follow-ups: How do you know when a component has grown too large and needs to be split up?;Does following this principle always mean creating more files and more complexity?

Component Composition & Children Props;Components & JSX