Reputation: 105
I'm studying ReactNative.Navigator.renderScene props.
'use strict';
import React,{Component} from 'react';
import ReactNative from 'react-native';
const {
TouchableHighlight,
Navigator,
AppRegistry,
Text,
View,
} = ReactNative;
class TestClass extends Component{
render(){
return <Text>test</Text>
}
}
class MyTag extends Component{
render(){
return <Text>test</Text>
}
}
class Main extends Component{
render(){
const routes =[{component:TestClass,index:0},{component:MyTag,index:1}]
return(
<Navigator
initialRoute={routes[0]}
initialRouteStack={routes}
renderScene={(route, navigator) =>
<View><TouchableHighlight onPress={() => {
if (route.index === 0) {
navigator.push(routes[1]);
} else {
navigator.pop();
}
}}><View>{route.component}</View>
</TouchableHighlight></View>
}
/>
)
}
}
AppRegistry.registerComponent('ChoiceComponent', () => Main);
Can component in routes variable be called by using {route.component} in renderScene props in JSX?
TestClass is called correctly if {route.component} is changed into <Test Class />.
Upvotes: 4
Views: 471
Reputation: 1074028
You're asking if you can use an object property (route.component
) in place of a class name. Absolutely! Remember, these are just identifiers. You use it exactly the same way you used the class name.
So instead of
{route.component}
you want
<route.component />
(But keep reading, we may have to do more.)
Example:
class Example1 extends React.Component {
render() {
return <div style={{color: "blue"}}>{this.props.text}</div>;
}
}
class Example2 extends React.Component {
render() {
return <div style={{color: "green"}}>{this.props.text}</div>;
}
}
const routes = [
{component: Example1},
{component: Example2}
];
ReactDOM.render(
<div>{routes.map(route => <route.component text="Hi there" />)}</div>,
document.getElementById("react")
);
<div id="react"></div>
<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>
The above works, but as far as I can tell from the React documentation, our component identifier name should start with a capital letter:
User-Defined Components Must Be Capitalized
When an element type starts with a lowercase letter, it refers to a built-in component like
<div>
or<span>
and results in a string'div'
or'span'
passed toReact.createElement
. Types that start with a capital letter like<Foo />
compile toReact.createElement(Foo)
and correspond to a component defined or imported in your JavaScript file.
In our case, it's route.component
, which is currently handled correctly (because of the .
; it wouldn't if it were route_component
, for instance), but that appears to be undocumented behavior. (Supporting the .
is documented behavior, what appears undocumented is allowing you to start with a lower-case letter when it's not a simple identifier.)
So I think to be officially in line with the docs, we'd want to assign that to a capitalized identifier:
const RouteComponent = route.component;
return <RouteComponent text="Hi there" />;
Like so:
class Example1 extends React.Component {
render() {
return <div style={{color: "blue"}}>{this.props.text}</div>;
}
}
class Example2 extends React.Component {
render() {
return <div style={{color: "green"}}>{this.props.text}</div>;
}
}
const routes = [
{component: Example1},
{component: Example2}
];
ReactDOM.render(
<div>{routes.map(route => {
const RouteComponent = route.component;
return <RouteComponent text="Hi there" />;
})}</div>,
document.getElementById("react")
);
<div id="react"></div>
<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>
Upvotes: 3