← Back to list

Smart vs Dumb Components |Angular

Picture this: you’re building an Angular app, and you’ve got components everywhere. Some of these components are like the manager of a…

Assiljanbeih · 2025-09-09 08:51 · 0 claps · 3.7 min read
#components #angular #smart-component #dumb-components
Open on Medium ↗
Wiki topics: 🌐 · Web Development

Smart vs Dumb Components |Angular

Photo by Mohammad Rahmani on Unsplash

Photo by Mohammad Rahmani on Unsplash

Picture this: you’re building an Angular app, and you’ve got components everywhere. Some of these components are like the manager of a restaurant — they know everything, they make decisions, they talk to the kitchen (your services), and they coordinate everything. These are your smart components.

Then you’ve got other components that are like the waiters — they just take what they’re given and present it nicely. They don’t make big decisions, they don’t talk to the kitchen directly, they just do their job with what you hand them. These are your dumb components (though we often call them “presentational” components because “dumb” sounds a bit harsh).

Smart Components: The Decision Makers

Let me show you what a smart component looks like. Imagine we’re building a user dashboard:

@Component({
  selector: 'app-user-dashboard',
  template: `
    <div class="dashboard">
      <app-user-profile [user]="currentUser" (userUpdated)="onUserUpdate($event)"></app-user-profile>
      <app-user-stats [stats]="userStats"></app-user-stats>
      <app-notification-list [notifications]="notifications" (dismiss)="dismissNotification($event)"></app-notification-list>
    </div>
  `
})
export class UserDashboardComponent implements OnInit {
  currentUser: User;
  userStats: UserStats;
  notifications: Notification[];

  constructor(
    private userService: UserService,
    private notificationService: NotificationService
  ) {}

  ngOnInit() {
    // This component knows HOW to get data
    this.userService.getCurrentUser().subscribe(user => {
      this.currentUser = user;
    });

    this.loadUserStats();
    this.loadNotifications();
  }

  onUserUpdate(updatedUser: User) {
    // It makes decisions about what to do with events
    this.userService.updateUser(updatedUser).subscribe(() => {
      this.currentUser = updatedUser;
      this.loadUserStats(); // Maybe we need to refresh stats
    });
  }

  dismissNotification(notificationId: string) {
    // It handles business logic
    this.notificationService.dismiss(notificationId).subscribe(() => {
      this.notifications = this.notifications.filter(n => n.id !== notificationId);
    });
  }
}

See what’s happening here? This component is the boss. It:

  • Knows how to fetch data from services
  • Makes decisions about what to do when things happen
  • Manages state and coordinates between different parts
  • Handles all the business logic

Dumb Components: The Specialists

Now let’s look at one of those child components — a dumb one:

@Component({
  selector: 'app-user-profile',
  template: `
    <div class="user-profile">
      <img [src]="user?.avatar" [alt]="user?.name">
      <h2>{{user?.name}}</h2>
      <p>{{user?.email}}</p>
      <button (click)="editProfile()" class="edit-btn">Edit Profile</button>
    </div>
  `
})
export class UserProfileComponent {
  @Input() user: User | null = null;
  @Output() userUpdated = new EventEmitter<User>();

  editProfile() {
    // It doesn't know HOW to save data, it just announces what happened
    const updatedUser = { ...this.user, lastModified: new Date() };
    this.userUpdated.emit(updatedUser);
  }
}

This Matter?

You might be thinking, “Okay, but why should I care about this pattern?” Well, let me tell you why this is actually brilliant:

Testing becomes a breeze. When you want to test that user profile component, you just pass it some fake data and check if it renders correctly. You don’t need to mock services or worry about HTTP calls or any of that complexity.

Reusability is incredible. That user profile component? You can drop it anywhere in your app. Maybe you want to show user profiles in a list, in a modal, in a sidebar — doesn’t matter. It just takes a user object and does its thing.

Your app becomes predictable. When something breaks, you know exactly where to look. If the data is wrong, check the smart component. If the display is wrong, check the dumb component.

The Golden Rules I Follow

When I’m building Angular apps, I stick to these principles:

For Smart Components:

  • They can inject services and talk to APIs
  • They manage application state
  • They coordinate between multiple child components
  • They handle routing and navigation logic
  • They’re often tied to specific pages or major features

For Dumb Components:

  • They only receive data through @Input()
  • They only communicate up through @Output() events
  • They have no dependencies on services (well, maybe some utility services)
  • They’re focused on presentation and user interaction
  • They should work in isolation with just the right inputs

A Real-World Example

Let me give you a concrete example. Say you’re building an e-commerce app:

Your smart component might be ProductListPageComponent. It:

  • Fetches products from the API
  • Handles search and filtering
  • Manages pagination
  • Deals with loading states and errors

Your dumb components might be:

  • ProductCardComponent - just shows a product nicely
  • SearchBarComponent - just emits search terms when user types
  • PaginationComponent - just shows page numbers and emits when clicked

The smart component orchestrates everything, while the dumb components are like specialized tools that do one thing really well.

Common Mistakes I See People Make

Making everything smart. I see developers injecting services into every component. Don’t do this! If a component doesn’t need to make decisions or fetch data, keep it dumb.

Going overboard with dumb components. Sometimes you need a component to be a little smart. If it makes your code cleaner and more maintainable, it’s okay to inject a service or two.

Forgetting about OnPush. Dumb components are perfect candidates for ChangeDetectionStrategy.OnPush because their inputs are predictable. This can give you nice performance gains.

The Bottom Line

Think of smart and dumb components like a good restaurant. You’ve got the head chef (smart component) who knows all the recipes, manages the kitchen, and coordinates everything. Then you’ve got specialized stations (dumb components) — one person just grills, another just makes salads, another just plates desserts.

Each person is really good at their specific job, and the head chef coordinates them all. If the salad station breaks down, you can fix or replace it without affecting the grill. If you want to add a new salad station, you can do that easily too.

That’s the power of this pattern — it makes your Angular app more maintainable, testable, and scalable. And honestly? Once you start thinking this way, you’ll never go back.


메타데이터
post_id
d4c8edffa642
slug
smart-vs-dumb-components-angular-d4c8edffa642
url
https://medium.com/@assiljanbeih/smart-vs-dumb-components-angular-d4c8edffa642
canonical_url
https://medium.com/@assiljanbeih/smart-vs-dumb-components-angular-d4c8edffa642
author_url
https://medium.com/@assiljanbeih
status
ok
fetched_at
2026-06-10 09:45:17