jhegedus jhegedus - 10 months ago 54
React JSX Question

Circular definition in React's render method when using react-router

What is

in React?

What defines these children?

Are they defined in a component's render method? I assume yes.

Are children always rendered? If yes, then why do I need to manually put
into the render method when using react-router? How does that make any sense ?

This is what I mean :

// modules/App.js
// ...
render() {
return (
<h1>React Router Tutorial</h1>
<ul role="nav">
<li><Link to="/about">About</Link></li>
<li><Link to="/repos">Repos</Link></li>

{/* add this */}

// ...

Taken from this tutorial.

How does this not blow up due to circular definition?

Render method defines what is in
but render method itself contains

Why is this not a problem ?

Why is it needed to make this circular definition in the first place ?

I am confused.



import React from 'react'
import { render } from 'react-dom'
import App from './modules/App'
import { Router, Route, hashHistory } from 'react-router'

// insert into index.js
import About from './modules/About'
import Repos from './modules/Repos'

// index.js
// ...
<Router history={hashHistory}>
<Route path="/" component={App}>
{/* make them children of `App` */}
<Route path="/repos" component={Repos}/>
<Route path="/about" component={About}/>


), document.getElementById('app'))

Answer Source

The clue to this answer is that children lives under the props of the component. Basically, this.props.children is nothing more than a property of the component. Granted it is a somewhat special prop and an opaque data structure, but it is a prop nonetheless.

What this means is that render does not define what this.props.children is. Like any other prop, children is passed down from a parent component to a child. There is nothing fantastically special about this.props.children except it acts as a handy, built-in way to pass arbitrary inner elements from parent to child.

Passing children to a component like this:


Is not so different than doing it like this (and in fact you CAN do it like this, but it would be silly to do so because you end up bypassing some important React housekeeping):

<MyComponent children={[<div>Hello</div>, <div>World</div>]} />

So, there is no circular logic here. Components receive their children from their direct parent as a prop. The only thing that render does is define how a component is rendered. render is the presentational part of the component and is intentionally disconnected from the data model. If you did not put {this.props.children} into the render method, then the children simply wouldn't be displayed.

Since children are much like any other component prop, and they are represented as an array, you can do convenient stuff like using Array.map to modify or wrap each child in some way:

render() {
    <div>{this.props.children.map(function(ea){return <strong>{ea}</strong>})}</div>

I hope that clears it up for you.