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/