Search code examples
angularcomponents

How can I ensure a [shared] component is truly a dumb component? (Angular)


I'm working on a project for work where I'm trying to segregate unnecessary api calls, logic and other code which could otherwise duplicate work, or make the application slow and hurt performance. To be honest, removing api calls from shared components was the first step. However I'm looking for some guidance on the best practices I can follow.

For angular specifically, are shared components allowed to make navigation calls? I'm aware that api calls should be avoided (maybe it might just be the nature of the application I was working on) , again, I would appreciate any thoughts anyone has or links to readings.

Also it's pretty obvious by my question that I'm new to angular and still a beginner in coding


Solution

  • Dumb Components are usually used for presentational purposes. They can not include heavy logic. To make sure the your component is really dumb, try checking the following:

    1. Your components is mainly interested in the UI, meaning it's used to present data in an elegant way. It usually gets this data from its container component using input variables (the ones decorated with @Input).
    2. If the component needs to perform a particular action that requires heavy logic, it should delegate that to its container component using @Output.
    3. Try not make HTTP calls or subscribe (use the async pipe instead) inside your dumb component.

    I would advise you have a look at those videos here and here from Joshua Morony, they helped me a lot

    Edit

    The description mentioned above works well with simple relationships (a parent component with a direct child component). However, when this chain starts to get longer, you have to deal with the so called extraneous properties or custom event bubbling problem. To clarify, that happens when you have something like this:

    GrandParentComponent
    --- ParentComponent
    ------ ChildComponent
    ---------GrandChildComponent
    

    Now, let's assume that your container (aka smart) component (GrandParentComponent) needs to pass some data to its direct child (ParentComponent). As mentioned before, that is absolutely fine. But what if it needs to pass that data to the (GrandChildComponent)? In this case, you'll have to take the following route in order to pass your data:

    GrandParentComponent > ParentComponent > ChildComponent > GrandChildComponent
    

    You will have to do the opposite if you wanted to propagate an event the other way around (from the GrandChildComponent to the GrandParentComponent) since Angular Custom Events do not bubble.

    This, indeed, is a lot of boilerplate to do a simple task. But this is how it works and you have to accept that. Alternatively, You can use a shared service or an immutable store (i.e. NgRx Global/Component Store) that has all the data required for this feature. Then, every component that needs access to this data will inject that service/store. And if those children want to propagate some events, they can do that with a Subject or an Action.