What to keep as presentational and container in Reactjs? - reactjs

I am using React and Redux.
I have a question regarding what to keep as a Presentational and what to keep as container component
I have an App, which will have 3 sections
A carousel of banners
A collections for campaigns, each campaign will have products
A brand collection where each brand will have certain products
And products will have an action i.e. Add to Cart and same products can exist b/w Brands and Campaigns
3 API's are available one for each for getting data.
<App> ==> Presentational
<Banners/> ==> Container
<Campaigns/> ==> Container
<Brands/> ==> Container
</App>
Is my approach correct on this?

I think ultimately there is no "right" or "wrong" approach, it's simply a case of what works best for you.
If you are wanting to maintain a separation of container and presentational components, then as long as you stick to the principals you can compose your application in any way that makes sense.
E.g. I have presentational components that have container components composed within them - at some stage down the component tree there will be a purely presentational component that knows how stuff should look given its props and passes off event handlers to the container that controls it.
In the context of your app, this may look like:
<App> // Component provided it is simply composing other components and has no state etc
<BannersContainer/> // I assume that this is going to hook up to Redux actions and state with react-redux and may wrap a presentational <Banners/> component?
<CampaignsContainer/> // As above, except wrapping presentational <Campaigns/> component?
<BrandsContainer/> // As above except wrapping presentational <Brands/> component?
</App>
Then within your <Banners />, <Campaigns /> and <Brands /> presentational components, they too may compose themselves of both presentational and container components, depending on what levels of your component tree you may want to further hook into Redux state at.

I don't think that you should categorize in presentational/container groups based on content. Your question makes me think that you're splitting them based on what these components contain while you should be asking yourself what are they doing. I could easily find a presentational layer in every of these four components. For example the App may contain some layout grid markup which could be extracted or the banners for sure have some presentational markup because of the carousel.
My understanding for container is a component that knows where the data comes from and its structure so it can use it and pass whatever is needed down to the presentational component.
Often the presentational components have generic names like <GridColumn>, <NavHeader> or <CardTitle>. All these components above are really context specific so I would call them all container components.

You should keep components Presentational or Container as they end up to be. What I mean with this is that the context of the problem is more important than conventions.
In your case, let's take component and see how it will end up after connecting:
<App>
<Connect>
<Banners someProp={someDataFromStore}/>
<Banner> <Banner/>
<Banners/>
<Connect>
// ... other components
</App>
As you can see if you need someDataFromStore up in the component tree (App) or in other sibling components (Campaigns for example) you should connect it on a higher level, however, in some cases, it is better to connect them separately to avoid too much passing props down.
So the main point is to keep data flow as smooth as possible and to keep a single source of truth when it comes to data manipulations.

Related

Is it considered a bad practice to nest container component inside a presentational component? [duplicate]

I am new to react and redux. I have a scenario where there are nested components like this.
A > B > C > D
There is a property used in A component and it will be used in D component. So, I have two approaches:
Get state from redux store in component A and then pass it along as props to all it's child components even though it will be used only in D component.
I should connect to redux store in component D and fetch that property from there.
What is the correct approach?
As Dan Abramov, author of redux says in this issue
Both approaches of passing props down to children or connecting them
to the store are appropriate, however having nested connect()
components is actually going to give you more performance. The
downside is they're slightly more coupled to the application and
slightly harder to test, but that may not be a big issue.
He has also articulated a nice rule of thumb to follow on reddit
I do it this way:
Start by using one container and several presentational components
As presentational component tree grows, “middle” components start to pass too many props down
At this point, I wrap some leaf components into containers so that “middle” components don’t need to accept and pass down props that are
completely unrelated to them
Repeat
He has even tweeted regarding this:
Try to keep your presentation components separate. Create container
components by connecting them when it’s convenient.Whenever you feel like you’re duplicating code in parent components to provide data for same kinds of children, time to extract a container.
So in simple words:
You can use connect() at any level. Doing so makes the component smart, since it knows where its props come from. A dumb component just has props, and they could come from anywhere. A smart component is coupled to redux; a dumb component is not.
UPDATE: react-redux v7 and above
The same concept applies to useSelectors too. You can receive data in a container component and pass on to your presentational components, if multiple of its children make use of the same data
If however the data used by the children is different, you can choose to use useSelector individually within the child component. This will make sure that only those components re-render which actually need to
I would suggest if you are already using redux in your app then set the property in the redux store and fetch it in the component D.
But if the work flow is really simple and all the data is fetched from a single source per view, you can avoid redux as it is for complex state management.

What is the most efficient approach in a React Redux project that uses aggressive composition?

I'm developing a project that uses aggressive composition (each component will have lots of components in its tree and each of its components will have a significant number of components as well) and uses Redux to manage the state.
For example:
<ComponentA>
<ComponentB>
<ComponentC>
...
<ComponentZ>
</ComponentZ>
</ComponenetC>
</ComponentB>
</ComponentA>
Each of these components will have their own functions that can change the app's state.
What would be the most efficient approach to manage all the functions that change the state in the application?
-Use a Container component that connects ComponentA with the actions and pass all the functions down in the components tree
Example:
<ComponentA
funcB={this.props.funcB}
funcC={this.props.funcC}
...
funcZ={this.props.funcZ}
>
-Each component has it's own container so fewer functions will be passed down in the components tree but each component will need an additional component to have the connection:
<ContainerA>
<ContainerB>
...
<ContainerZ />
</Container>
</ContainerA>
One possible approach would be to connect a parent to Redux and let the connected parent drive its children so that children became aware of Redux store changes via the props passed to them by the parent. And change the store by calling parent's methods passed as props. However the grandkids of the connected parent would connect to Redux store themselves but not their children and so forth.
Each of these components will have their own functions that can change the app's state.
If their own functions change their own subset (or slice) of Redux store which other components don't need to be aware of and if the overall store is too big then you can consider splitting it into several independent stores. Link

What is proper or effective way for Composition of React Component?

I have multiple view in my application, I need helpl in how to use reusable component effectively ? Is it ohk if I create viewspecific component from reusable component ? - Generic Tree View . For users View which will render with user specific data and actions .
I have written re useable component in my react app.Which I have to use it with different data and action is it ohk to creat new component which use resuable component and provide data related to that ?
i.e
Component - DepartmentTree which renders and some functions related to Department. So finaly I will render
Component - usersTree same way here it calls and methods related to users . In the users view I will render
It's definitely OK to create a view-specific component that renders a reusable component. You could let this depend on how big your page is. If it includes a lot of components, then do split them up in view specific components.
About the data, you have a few options... First of all you could map the data response to a general structure that your TreeView component can read, so you only need to pass some props to the TreeView component. You could do this in the redux reducer.
If you require specific data different behaviour, but you still want to use the reusable TreeView component, you could think about creating a Higher Order Component. This component will wrap your reusable component and add some specific logic to it. You can read about it and see some good examples here: https://reactjs.org/docs/higher-order-components.html
The most important thing I always keep in mind: It's not always about how you finally do it, it's about keeping it simple, understandable and consistent.

Use Connect or pass data as props to children

I am new to react and redux. I have a scenario where there are nested components like this.
A > B > C > D
There is a property used in A component and it will be used in D component. So, I have two approaches:
Get state from redux store in component A and then pass it along as props to all it's child components even though it will be used only in D component.
I should connect to redux store in component D and fetch that property from there.
What is the correct approach?
As Dan Abramov, author of redux says in this issue
Both approaches of passing props down to children or connecting them
to the store are appropriate, however having nested connect()
components is actually going to give you more performance. The
downside is they're slightly more coupled to the application and
slightly harder to test, but that may not be a big issue.
He has also articulated a nice rule of thumb to follow on reddit
I do it this way:
Start by using one container and several presentational components
As presentational component tree grows, “middle” components start to pass too many props down
At this point, I wrap some leaf components into containers so that “middle” components don’t need to accept and pass down props that are
completely unrelated to them
Repeat
He has even tweeted regarding this:
Try to keep your presentation components separate. Create container
components by connecting them when it’s convenient.Whenever you feel like you’re duplicating code in parent components to provide data for same kinds of children, time to extract a container.
So in simple words:
You can use connect() at any level. Doing so makes the component smart, since it knows where its props come from. A dumb component just has props, and they could come from anywhere. A smart component is coupled to redux; a dumb component is not.
UPDATE: react-redux v7 and above
The same concept applies to useSelectors too. You can receive data in a container component and pass on to your presentational components, if multiple of its children make use of the same data
If however the data used by the children is different, you can choose to use useSelector individually within the child component. This will make sure that only those components re-render which actually need to
I would suggest if you are already using redux in your app then set the property in the redux store and fetch it in the component D.
But if the work flow is really simple and all the data is fetched from a single source per view, you can avoid redux as it is for complex state management.

Redux - Is it ok to pass props to child container components?

I am running into a situation where I am having to pass in props from the parent container component to the child container components so that the presentational components within the child container have an initial state. Is there another way of approaching this? Is this frowned upon?
Is the data in the Parent Container (the data you say is "from rails") being consumed by Redux? If not, then that is your real problem. Redux should be the one and only source of information for the react containers. Redux, in turn, should accept information from the Rails app and store that information within it's global state.
Once you've achieved this, you now have a single source of truth for all information feeding into the React Containers.
If a sub-component needs any information at all, it should receive them from the parent-container's redux state information.
It is ok to have nested sub-components. Simply continue to pass down information from 1 layer to the next. E.g. ContainerA, which receives name from redux, can render ComponentX with name={this.props.name} and ComponentX can then render ComponentY with name={this.props.name} again. This results in ComponentY being passed the information from Redux, through the parent component and container.
Your app should, naturally, have far more components than containers. That's a good thing. Components are inherently re-usable since they are only tied to a data shape rather than a data source. Use containers sparingly, and only when you want to insert specific information into a series of components.

Resources