When writing JSX, I sometimes need to create a top level element so the code will compile. For example, this won’t compile.
const routesList1 = ( <Route exact path="/link1" component={Link1UI}/> <Route exact path="/link2" component={Link2UI}/> )
But this will:
const routesList1 = ( <div> <Route exact path="/link1" component={Link1UI}/> <Route exact path="/link2" component={Link2UI}/> </div> )
Usually wrapping other React elements in a <div> works fine, but not always. So I’d like to know if I was forced to create a top level element to get the code to compile, can I later strip it off? If so how?
Below is a conceptual example of a problem I ran into with React router’s Switch element.
import react from 'react'; import { Route, Switch } from 'react-router-dom'; const routesList1 = ( <div> <Route exact path="/link1" component={Link1UI}/> <Route exact path="/link2" component={Link2UI}/> </div> ) const routesList2 = ( <div> <Route exact path="/link3" component={Link3UI}/> <Route exact path="/link4" component={Link4UI}/> </div> ) function stripDivFrom(reactElement) { reactElement.Children.toArray(); } class MyApp extends React.Component { render() { return ( <Switch> {stripDivFrom(routesList1)} {stripDivFrom(routesList2)} <Route exact path="/help" component={HelpUI}/> </Switch> ); } }
I provide this simplified example code so readers can understand what I’m asking.
I’m looking to get an answer to the question, not for a work around.
The question is: How can I get the children of a given react/JSX element? How can I change the stripDivFrom() function so that it works.
NOTE: The stripDivFrom() function currently doesn’t work. The Children property doesn’t is undefined (when I observe it in Chrome debugger). I found it when looking at the React source code but I’m obviously misunderstanding something. The browser console has an error that says: Uncaught TypeError: Cannot read property ‘toArray’ of undefined.
Updated
EDITED: After this question was asked, in React introduced a better solution to this problem.
In React 16.2.0 the component <React.Fragment>
was added which solves this problem.
The following is how the code would now loook:
const routesList1 = ( <React.Fragment> <Route exact path="/link1" component={Link1UI}/> <Route exact path="/link2" component={Link2UI}/> </React.Fragment> )
Advertisement
Answer
It will be available by element.props.children
.
Write it like this:
function stripDivFrom(reactElement) { return reactElement.props.children; }
In JSX expressions that contain both an opening tag and a closing tag, the content between those tags is passed as a special prop: props.children.
React elements are basically objects, check this example:
const element = ( <h1 className="greeting"> Hello, world! </h1> );
Object created by react will be:
const element = { type: 'h1', props: { className: 'greeting', children: 'Hello, world' } };
Check this: JSX Represents Objects
Working Code (style on wrapper div will not reflect in ui):
const hello = <div style={{color:'red'}}><div>Hello</div><div>World</div></div> class Game extends React.Component { a(el){ return el.props.children; } render() { return ( <div id="game-layout"> {this.a(hello)} </div> ); } } ReactDOM.render( <Game/>, document.getElementById('container') );
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script> <div id ='container'/>
working Fiddle: https://jsfiddle.net/mayankshukla5031/0cwueg7j/