DEV Community

Debug Diaries
Debug Diaries

Posted on

1 1 1

Understanding SOLID Principles in Frontend Development (with React Examples)

As frontend applications grow more complex, maintaining clean, scalable code becomes challenging. That’s where SOLID principles come in — a set of five design principles aimed at building better software. Though originally coined for object-oriented programming, they apply well to frontend development, especially when working with React.js.

In this blog, let’s break down each principle in simple terms with relatable React examples.

What is SOLID?

SOLID is an acronym:

  • S – Single Responsibility Principle
  • O – Open/Closed Principle
  • L – Liskov Substitution Principle
  • I – Interface Segregation Principle
  • D – Dependency Inversion Principle

Let’s explore each one.

1. Single Responsibility Principle (SRP)

A component should do one thing only.

// UI Component
function UserCard({ user }) {
  return <div>{user.name}</div>;
}

// Data Fetching Hook
function useUserData(userId) {
  const [user, setUser] = useState(null);
  useEffect(() => {
    fetch(`/api/users/${userId}`).then(res => res.json()).then(setUser);
  }, [userId]);
  return user;
}

Enter fullscreen mode Exit fullscreen mode

Each function does one job — one for UI, one for data. This separation makes the code easier to test, debug, and reuse.

2. Open/Closed Principle (OCP)

Components should be open for extension, but closed for modification.

function Button({ variant = 'primary', children }) {
  return <button className={`btn ${variant}`}>{children}</button>;
}

Enter fullscreen mode Exit fullscreen mode

You can add new button styles (secondary, danger, etc.) without modifying the Button component. This prevents bugs and keeps components flexible.

3. Liskov Substitution Principle (LSP)

A child component should work in place of its parent without breaking the app.

function Button({ onClick, children }) {
  return <button onClick={onClick}>{children}</button>;
}

function DangerButton(props) {
  return <Button {...props} className="danger" />;
}

Enter fullscreen mode Exit fullscreen mode

DangerButton behaves just like Button. If you replace Button with DangerButton, your app will still work — fulfilling the same expectations.

4. Interface Segregation Principle (ISP)

Components should only receive the props they actually use.

function UserSummary({ name, email }) {
  return (
    <div>
      <p>{name}</p>
      <p>{email}</p>
    </div>
  );
}

Enter fullscreen mode Exit fullscreen mode

Passing only required props keeps components simple and reduces the chance of misuse or confusion when reusing them.

5. Dependency Inversion Principle (DIP)

Depend on abstractions, not concrete implementations.

function Login({ authService }) {
  const handleLogin = () => authService.login();
  return <button onClick={handleLogin}>Login</button>;
}

Enter fullscreen mode Exit fullscreen mode

Instead of using a specific API method directly, Login depends on an authService. This allows easy mocking for tests and swapping out logic (e.g., for Google login or a mock server).

Conclusion

By applying SOLID principles, you:

  • Reduce bugs
  • Improve code reusability
  • Make your frontend easier to test and extend

Even if you're building a small app, following these principles leads to cleaner, more professional code. Start with Single Responsibility, and gradually adopt the rest as your projects grow.

Top comments (1)

Collapse
 
keizzmann profile image
The_Keizzmann😁🎹🎹💻

These are quite short, but really direct explanations to something that seems to go further as you explore. A perfect explanation for beginners too

Thanks