2

I have this dashboard creating app that has pretty deeply nested components and I need to propagate state, such as the current dashboard, down to these components. The current dashboard is a rather large object that contains all information about the what widgets are in this dashboard, where they are, how they look, etc.

Right now I'm calling to a database, converting the data to the dashboard object, then rendering the dashboard by passing this object to components such as the tool bar, side bar, canvas, widgets. These child components might change the properties of the dashboard object but never the dashboard object itself so I don't think I need output.

It works fine but some components have too many inputs and they even sometimes need outputs. It's getting pretty messy.

I was thinking of just creating a service that manages the state for the entire app. I can't find much information online about best practices, just many ways of doing the same thing. If anyone can provide any information on why using one method of state management is better than another, that would be great!

Austen Stone
  • 948
  • 1
  • 10
  • 21
  • There are complete libraries to manage state. Each with its pros and cons. For your simple use case id start by googling "Behavior subject state managment" and work my way through there – Stavm Mar 08 '20 at 18:01

2 Answers2

-1

We can pass data from one component to another by

  1. using @Input, @Output (Component Interaction)
  2. using services
  3. using route param
  4. using resolver

1) Component Interaction @Input and @Output we can pass data by event emitter.

2) @Injectable({'providedIn':'root'}) this will be a service in your entire project(Singleton). We can access the members in service by creating an object in the component

3) We can append data in your url params by using navigate and navigateByUrl in Router. And we can get data in the component by using ActivatedRoute Example:

this._ActivatedRoute.queryParams.subscribe((params: Params) => {
        if(params){
        }
});

4) By using resolver we can set data in the ActivatedRoute. While navigation we can perform the action in the resolver function. We can implement this in different ways. If you want to perform this action in parent route then you can add this resolver in the parent router declaration. Or you need to trigger this function in a particular component navigation you can give in that particular router declaration. Or you can navigate to this resolver.

Implementation 1

{
    path: '',
    resolve: [
     authdetails: UserAuthResolver
   ],
   children: [{
    path: 'a',
    component: ComponentA,
   },{
    path: 'b',
    component: ComponentB,
   }]
  }

In this implementation you can trigger the resolver while parent route navigation.

Implementation 2

{
    resolve: [
     authdetails: UserAuthResolver
   ],
    path: '',
    component: dashboard,
   }

In this implementation you can trigger the resolver on every component click. And this authdetails can access in the component by using ActivatedRoute.

Implementation 3

{
    path: 'logout',
    resolve: {
      logout: LogoutResolver
    }

In this implementation you can perform only the action written in the LogoutResolver. Here there is no component routing.

All these are based on the usecases. I think resolver is better for you.

Hope this will helpful for you

Happy Coding

-1

I don't think there is a single correct answer here, this depends from use-case to use-case. I have tried to answer your question as best as I can based on my experiences, but I am not a 100% sure about all of it.

I think there are two main things to consider here, do we want to optimize for code readability / maintainability or runtime performance.

Code readability / maintainability

Splitting up into smart components and dumb components is a best practice for code readability / maintainability. Your smart components should hold most of your JS logic and communication with the services. The dumb components should not inject services, but instead communicate with their parents through Inputs and Outputs. Some of the benefits this gives is:

  1. The dumb components can be reusable at they don't depend on any serices.
  2. It is very easy to understand the logic of a dumb component as the only thing that affect them in the Inputs and Outputs
  3. The dumb component becomes easy to test as they can live in isolation without any services
    1. The runtime performance can be improved as you con use OnPush change detection strategy (More on this in the next section)

But as you are saying, when you start to have a lot of Inputs and Outputs, it starts to become messy, and I agree with that.

I usually start to consider if a dumb component should become a smart one when I reach 6 or more Outputs and Inputs in total in a single component. Also if I have to pass the data several steps up or down I would consider turning a dumb component into a smart one.

I also think the potential for reusability is important. If the component have a great potential for being reused, I will accept that it has many Inputs and Outputs. If I know that it will never be reused, I might as well make it smart and bring the services in.

Performance

When it comes to performance, I believe that having as much of your HTML as possible inside dumb components always will be the best. This is because you then can optimize these components by using change detection strategy OnPush.

SnorreDan
  • 2,740
  • 1
  • 14
  • 17