ReactJS: Why use this.props.children? - reactjs

I've realised that none of the components I write use {this.props.children}.
I tend to compose my components the way the official docs state at the top of https://facebook.github.io/react/docs/multiple-components.html.
Is nesting the components like this...
<A>
<B />
<C />
</A>
...beneficial over composing them like this?:
A.js
render() {
<B />
<C />
}
Presuming that's the right terminology, what am I missing?

In my applications I rarely use this.props.children, because I often know specifically what children I want to render. In libraries, or components written to be re-used outside of a specific component hierarchy, I've seen it often. I think this.props.children has more relevance to that use-case.
Edit: I thought I'd elaborate on some cases that this.props.children can come in handy. One such example is when creating components which follow the 'render prop' pattern. i.e. I've got some components that require pulling data in from multiple 'render prop' HoC's, such as an Apollo Query component as well as a state management HoC. I combined all my different data sources into one HoC and then called children as a function, passing in the result of pulling out all the data I needed. That being said these days I prefer and look forward to wider adoption of Hooks as an alternative to render props.
Really any component which you want to render arbitrary children; another example I've used props.children is when creating a HoC that required a user be authenticated before rendering the child, redirecting to a login screen when the user isn't logged in. I could wrap any of my 'protected' screen components with this auth HoC.
It's still something the majority of my components don't use, but just another tool to be applied when the situation warrants.

I'd say it would be useful when you don't know what you want to render.
For instance, you have a tooltip wrapper, let's say it's A component in your scenario, and you can use it to pass different content:
<A>
<div>Some text...</div>
<ImageComponent /> // render an image as well
</A>
Or:
<A>
<div>Only text</div>
</A>

Some components don't know their children ahead of time. This is especially common for components like Sidebar or Dialog that represent generic "boxes".
We recommend that such components use the special children prop to pass children elements directly into their output:
Read More...

Children is a special prop that can be passed from the owners to the components defined inside their render method. It allows us to customize a structure of a component.
With props, a child component keeps its structure under the full control and only certain attributes or values are allowed to be passed. The structure of the component is hard coded.
In the React documentation, children property is described as opaque, because it is a property that does not tell anything about the value it contains. As a result it allows a client/parent to customize a structure.
We can also say, that the components defines only a kind of basic template/structure, for instance by providing a kind of "header". And the consumer reuses this header structure, by adding children.

Related

Passing props with React Router

So I'm still learning React, but I feel like I understand at least the "basics". However, Routing with React router and just general "architecture" is where I'm getting a little lost at.
I'm making a personal project app, but ill keep my descriptions/components generic for the explanation. Essentially I have 3 Main components right now:
<Table/> (Rendered in "App" and also the main / URL route, it's essentially just a bootstrap table. Also contains my state which is an array of objects (That will be eventually retrieved via JSON via a GET request to an API)
<Row/> (A single row of data on the table, represented by 1 object in the array of objects from the state provided in <Table/>. Also contains a button that takes you to the "View" page/component below)
<View/> (What is going to be a "View/Details" page for the Row)
So I imagine my route for <View/> is going to be something like <Route path="/:id/view" children={<View/>} /> (Keeping it super simple and generic right now just for the explanation)
Sidenote: How come sometimes I see <Route> wrapping a component and sometimes I see <Route> defined with the children prop pointing at the Component to render?)
Anyways...the button in <Row/> will be a <Link to={'{$props.id}/view'}> I think....however how exactly do I pass the props down to <View/> based on the :id param? I need to pass the data I receive in the <Row/> component onto the <View/> component (Because within the <Row/> component is where I link to <View/>.
I suppose ONE option would be to do something like let {id} = useParams(); and then do a GET request specific for that particular resource from the API. But considering I'm already passing the data down to each row and it's available in the state within <Table/> it seems like an unnecessary HTTP request.
Im probably making this more complex than I need to, but I need to pass the "data" all the way down from <Table/> to the <View/> component depending on the data id. And I'm not really sure how to set up React router to do that. Hopefully what I'm asking makes sense.
To answer your first question, I'll reference the react-router documentation as this is answered in the subsection named "route render methods".
The tldr of the above is simply that the "preferred" method of rendering components via <Route/> is by supplying actual children to the component. However, there are other methods and specific use cases that go along with each.
As for the core issue you're asking about: What you'll want to do is use an object in the <Link /> component that persists a state to the <View /> element that has all of the information that it will need. You can find react-router's documentation on this here.

React props vs children. What to use when?

What is the difference between the two approaches ?
Passing text for a button as props
<TextComponent title="Save"/>
function TextComponent(props){
return <button>{props.title}<button/>
}
vs
Passing text as a child
<TextComponent>Save<TextComponent />
function TextComponent(props){
return <button>{props.children}<button/>
}
children prop is something that you use when the structure of what needs to be rendered within the child component is not fixed and is controlled by the component which renders it.
However if behaviour of the component is consistent across all its renders it can define the specific props that it needs and the parent can pass them to it.
A very simple example could be a Navbar which can use children. For a Navbar the items that it needs to render as well as the order or alignment or items depends on how it needs to be used at different instances or across different pages. For instance Navbar somewhere can have Search component at one place and at some other place not have it. Also the menus may sometimes be needed to the left followed by Login menu item to the right and a searchbar between them and sometimes they may all be present to the right without the searchbar. In such cases the parent component can control how the internal structure would be
You should use children when you don't know them ahead of time, see: https://reactjs.org/docs/composition-vs-inheritance.html
Here, if you KNOW that you'll use a title inside your child component, just use a named prop.
I'd say that if you ask yourself the question: "Ok, but what will that generic component render?" is when you should use children
You use props.children on a component which acts as a container and does not know about their children ahead of time.
Basically props.children it is used to display whatever you include between the opening and closing tags of the "containing" component when invoking it.
As mentioned in the React official docs:
Some components don’t know their children ahead of time. This is especially common for components like Sidebar or Dialog that represent generic “boxes”.
We recommend that such components use the special children prop to pass children elements directly into their output:
Simply put, it props.children just displays whatever is put between the opening and closing tags.
As asked in your question, there is not much difference in the use case specified by you.
But, say you had a small left icon the component then passing 'title' as a separate prop would make more sense Eg.
<TextComponent title="Save" src="https://..." />
function TextComponent(props) {
return (
<div>
<img src={props.src}/>
<button>{props.title}<button/>
</div>
);
}
When you do know what your props are, use props. Otherwise, use children (aka containment).
Other than that, using props/children in your case depends on what you want to pass:
If its a single props (like item), than it doesn't matter which method you'll choose.
Else, you should check what you are passing inside children as you might pass other values which you don't want to render.
I would suggest using the selective approach (e.g props.title), since you are always aware of whats going inside your components.

What to keep as presentational and container in 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.

How to handle layout containers which do not match component hierarchy?

As far as I've understood, in React, components should communicate in an hierarchical order through the nested hierarchy. Given this, how should it be handled when an application's layout container structure don't match the natural/expected/logical component hierarchy.
As an example of my question, I've come up with a scenario based on my app, that I'm not sure how to implement properly:
The screen is split vertically in two halves. This is done having two
div containers side by side. To each halve there's a corresponding
component: ItemsList and ItemDetails.
Nested inside ItemsList, there are several Item components we can
click on.
Each time there is click on an Item, the corresponding defined _itemID prop value needs to be sent to ItemDetails so it can load and display Item details in there.
The problem is, given the component structure, how can ItemDetails be a child of Item and still be on the right section of the screen where it's intended to be. (At least without some weird CSS which I want to avoid).
Here's the layout:
<div className="wrapper">
<div className="itemList" style="width:50%; display:inline-block;">
<div className="item">item1</div>
<div className="item">item1</div>
<div className="item">item1</div>
</div>
<div className="itemDetails" style="width:50%; display:inline-block;">
The details of the selected item.
</div>
</div>
I believe I could send information from a child to parent following up the hierarchy, but this don't seem practical. Considering this scenario is just a simplification of my actual problem (I have a lot more nested components), I believe this would make the code messy and confuse.
Is there a clean, simple way to achieve this in React? Am I missing some concept?
If it were me I would have a container component based off your wrapper. It would handle all state changes and be the source of truth for what the currently selected item is. Then you'd just need to pass a callback from the wrapper component through props down to your ItemsList that would handle setting the state of the active item.
Then you can just pass activeItem as a prop to the itemDetails component. It is a fairly common pattern to have a container component that manages state and passes callback functions down to child components that would allow them to create an action that changes the state of the container
The heirarchy would look like:
<Wrapper> // holds the state of active item and provides functions to change the active item
<ItemList /> // provides a list of items that when clicked sets active
<ItemDetail /> // shows the detail of the currently select item
</Wrapper>
Here is a pen of what i'm trying to explain
http://codepen.io/finalfreq/pen/KgEzgE
This always depends on many things. If you intend for a small project you are fine working with setState and refer to finalfreq's great answer. If you intend to scale well (aka grow without pain) then I would opt for a state management library.
I hate to be the guy who answers a simple question with "Use ... library! It's awesome!", and like I said, it really does not get much better than finalFreq's answer if you don't have the need to grow your app. A redux author even mentions that you should learn react without redux first, and you should not reach for it until you have a real need.
If you use redux then you should never have to worry about component structure for the sake of passing scope. Component structure if I am not mistaken(which I often am XD) should be based on what is easiest to understand and maintain, also performance comes to mind.
Your question is in the context of react, but I think this is really a state management and data communication question. I opt for redux.js lately(a pub/sub like library), but there are many alternatives. Redux requires a bit more typing, but offers extreme explicitness that you may appreciate as the project grows.
But the main reason I would reach for this is that it focuses on functional programming principles, and pushes your state mutations to the outer fringes of your app. This simplifies your code. If there is a bug it's easy to find(All mutations should be in the reducer files. You would also move your calculations to a util file which simplifies your code even more)
http://redux.js.org/

Reactjs - data flow

I have a general question about where to load data in Reactjs.
The main component is called App. Then the App returns 3 components: Header, Body, and Footer. Now within Body, there is a Tab component, which is further subdivided into a few components including a component called "grids".
Now I want my data (after being filtered) displayed in Grids.
Please correct me if I'm doing it wrong but my thinking is:
Load data in the main component App as state:
Pass it to Body with:
<Body data={this.state.data} />
In the Body component, pass it further as:
<Tabs data={this.props.data} />
In the Tabs component, pass it further as:
<Grids data={this.props.data} />
In Grids, write all the methods to filter data and display/return it accordingly.
Is this correct?
Thanks
The flow you've outlined is correct. An alternate approach is to use context: Anything set into context of one component is available to every descendent of that component, without setting props of intermediate components.
Context comes with a warning though:
Using context will make your code harder to understand because it
makes the data flow less clear. It is similar to using global
variables to pass state through your application.
BTW, for managing data, I'd use something like Flux or Redux. Managing data directly within React components quickly becomes a pain in a** as application grows. Flux/Redux, on the other hand, scale very well.

Resources