Frontend Development 17 min read

Five React Component Design Patterns with Advantages, Disadvantages, and Use Cases

This article introduces five reusable React component design patterns—Compound Component, Controlled Component, Custom Hook, Props Getters, and State Reducer—explaining their implementations, pros and cons, and suitable scenarios to help developers balance flexibility, complexity, and control in UI development.

政采云技术
政采云技术
政采云技术
Five React Component Design Patterns with Advantages, Disadvantages, and Use Cases

As a React developer you may encounter challenges such as building highly reusable components for various business scenarios, creating simple and easy‑to‑use APIs, and ensuring UI and functional scalability.

To address these, five React component design patterns are presented, each with its strengths, weaknesses, and appropriate use cases.

1. Compound Component Pattern

The compound component pattern composes multiple simple components into a more complex one, separating logic and allowing each sub‑component to handle a specific task. It reduces API complexity by passing props directly to child components instead of a single container.

import React, { useState } from 'react';

// Basic button component
const Button = ({ label, onClick }) => (
{label}
);

// Basic text input component
const TextBox = ({ value, onChange }) => (
);

// Compound component
const LoginPanel = () => {
  const [username, setUsername] = useState('');
  const [password, setPassword] = useState('');

  const handleLogin = () => {
    console.log(`Logging in with ${username} and ${password}`);
  };

  return (
setUsername(e.target.value)} />
setPassword(e.target.value)} />
);
};

export default LoginPanel;

Advantages:

API complexity is lowered; props are passed directly to relevant children.

High reusability of basic components.

Clear separation of concerns.

Disadvantages:

More JSX lines and deeper component trees increase code size.

Not ideal for simple scenarios where the pattern adds unnecessary overhead.

Applicable scenarios: complex forms, dialog/modal composition, and any UI that benefits from splitting into independent sub‑components.

2. Controlled Component Pattern

This pattern turns a component into a controlled one by managing its internal state through props, which is especially useful for form elements.

import React, { useState } from 'react';

const ControlledLoginPanel = () => {
  const [loginData, setLoginData] = useState({ username: '', password: '' });

  const handleInputChange = e => {
    const { name, value } = e.target;
    setLoginData(prev => ({ ...prev, [name]: value }));
  };

  const handleLogin = () => {
    console.log(`Logging in with ${loginData.username} and ${loginData.password}`);
  };

  return (
Login
);
};

export default ControlledLoginPanel;

Advantages:

Provides fine‑grained control over component state.

Ensures predictable behavior by keeping state in a single source of truth.

Disadvantages:

More boilerplate code for each input.

Potential performance overhead due to frequent re‑renders.

Not suitable for very simple forms.

Applicable scenarios: dynamic form fields, modal visibility control, and any situation requiring real‑time validation or inter‑field coordination.

3. Custom Hook Pattern

Custom hooks extract reusable logic (state, handlers, etc.) into a separate function, allowing components to focus on UI rendering.

import React, { useState } from 'react';

const useLoginForm = () => {
  const [loginData, setLoginData] = useState({ username: '', password: '' });

  const handleInputChange = e => {
    const { name, value } = e.target;
    setLoginData(prev => ({ ...prev, [name]: value }));
  };

  const handleLogin = () => {
    console.log(`Using ${loginData.username} and ${loginData.password}`);
  };

  return { loginData, handleInputChange, handleLogin };
};

const ControlledLoginPanel = () => {
  const { loginData, handleInputChange, handleLogin } = useLoginForm();
  return (
登录
);
};

export default ControlledLoginPanel;

Advantages:

Logic reuse across multiple components.

Cleaner component code focused on presentation.

Disadvantages:

Higher conceptual complexity; developers must understand the separation between hook and UI.

Applicable scenarios: shared data fetching, complex state handling, and side‑effect encapsulation.

4. Props Getters Pattern

Props getters return a set of props via a function, giving developers explicit control over what is passed to child components while keeping the component API simple.

import React, { useState } from 'react';

const Button = ({ getLabel, handleClick }) => (
{getLabel()}
);
const TextBox = ({ getValue, onChange, placeholder }) => (
);

const ControlledLoginPanel = ({ getUsernameProps, getPasswordProps, handleLogin }) => (
'Login'} handleClick={handleLogin} />
);

const useLoginForm = () => {
  const [loginData, setLoginData] = useState({ username: '', password: '' });
  const handleInputChange = name => e => setLoginData(prev => ({ ...prev, [name]: e.target.value }));
  const handleLogin = () => console.log(`Logging in with ${loginData.username} and ${loginData.password}`);
  const getUsernameProps = () => ({ getValue: () => loginData.username, onChange: handleInputChange('username') });
  const getPasswordProps = () => ({ getValue: () => loginData.password, onChange: handleInputChange('password') });
  return { getUsernameProps, getPasswordProps, handleLogin };
};

export default function App() {
  const { getUsernameProps, getPasswordProps, handleLogin } = useLoginForm();
  return
;
}

Advantages:

Easy to use – developers just pass the getter to the appropriate JSX element.

Clear separation of concerns; component focuses on rendering.

Reduces nesting compared with raw hooks.

Disadvantages:

Less visible; getters act as a black box.

May introduce additional callbacks, increasing perceived complexity.

Creates external dependencies on the getter functions.

Applicable scenarios: data filtering components, form validation wrappers, and any UI where prop generation logic benefits from encapsulation.

5. State Reducer Pattern

The state reducer pattern delegates state updates to a reducer‑like function, offering fine‑grained control over complex state transitions.

import React, { useState } from 'react';

const TextInput = ({ getInputProps }) => {
  const inputProps = getInputProps();
  return
;
};

const StateReducerExample = () => {
  const [inputValue, setInputValue] = useState('');
  const stateReducer = (state, changes) => {
    if (changes.value && changes.value.length > 10) return state;
    return { ...state, ...changes };
  };
  const getInputProps = () => ({
    value: inputValue,
    onChange: e => setInputValue(stateReducer({ value: e.target.value })),
  });
  return (
State Reducer Example
);
};

export default StateReducerExample;

Advantages:

Flexible state management for complex scenarios.

Centralized update logic improves code organization.

Clear, explicit handling of each state change.

Disadvantages:

Introduces additional abstraction, increasing code complexity.

May lead to redundant code for simple state updates.

Overkill for straightforward components.

Applicable scenarios: components with intricate state interdependencies, asynchronous updates, or where conditional state transitions must be tightly controlled.

Conclusion

These five patterns illustrate the trade‑off between component flexibility (control) and implementation complexity. Choose the pattern that best matches your business requirements and the expertise of your development team.

Design PatternsfrontendjavascriptreactComponent Design
政采云技术
Written by

政采云技术

ZCY Technology Team (Zero), based in Hangzhou, is a growth-oriented team passionate about technology and craftsmanship. With around 500 members, we are building comprehensive engineering, project management, and talent development systems. We are committed to innovation and creating a cloud service ecosystem for government and enterprise procurement. We look forward to your joining us.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.