the_commander_x
the_commander_x

Reputation: 105

Can class object be called from React Component Prop?

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

Answers (1)

T.J. Crowder
T.J. Crowder

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 to React.createElement. Types that start with a capital letter like <Foo /> compile to React.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

Related Questions