user3622460 user3622460 - 4 years ago 136
React JSX Question

How can I display React component based on prop name passed into a container?

UPDATE Solved poorly with

const curSlide = this.props.name;

const setView = () => {
if(curSlide === 'Slide1') {
return <Slide1 />
} else if(curSlide === 'Slide2') {
return <Slide2 />
} else {
return <Slide3 />
}
}

return(
<div>
<center>
{setView()}
</center>
</div>


I have a story that contains a slide container which hosts different components. I have a button under my story container that when pressed passes this.props.name + 1 to the slide container. I would like the slide container to be able to use this information and render out the proper Slide based on the button click.

I am not sure why nothing is showing up when the button is clicked.

Story.js

import React, { Component, PropTypes } from 'react'
import sass from '../scss/application.scss'
import SlideContainer from './SlideContainer'


class Story extends Component {
constructor(props){
super(props)
this.state = {
name: '',
count: 0
}
}

handleClick(e) {
e.preventDefault();
let tempCount = this.state.count + 1;
let curSlide = `Slide${tempCount}`;

this.setState({
name: curSlide,
count: tempCount
});

}

render() {
return(
<div>
<div>
<SlideContainer name={this.state.name}/>
</div>
<center><button className="btn btn-danger" onClick={this.handleClick.bind(this)}>
<span className="glyphicon glyphicon-heart"></span></button>
</center>
</div>
)
}
}


Story.propTypes = {
name: PropTypes.string,
count: PropTypes.number
}

export default Story;


SlideContainer.js

import React, { Component, PropTypes } from 'react'
import sass from '../scss/application.scss'
import Slide1 from './Slide1'
import Slide2 from './Slide2'


class SlideContainer extends Component {
constructor(props){
super(props)
this.state = {
name: ''
}
}

render() {

let curSlide = this.props.name;

return(
<div>
<center>
<curSlide />
</center>
</div>
)
}
}

SlideContainer.propTypes = {
name: PropTypes.string
}

export default SlideContainer;

Answer Source

You need to somehow map the name of your component to the actual component instance. You might be able to make it work by doing something like this:

import Slide1 from './Slide1'
import Slide2 from './Slide2'

class SlideContainer extends Component {
    constructor(props){
        super(props)
        this.state = {
            slideMapping = {
                'Slide1': Slide1,
                'Slide2': Slide2,
            };
        }
    }  


    render() {

        let curSlide = this.state.slideMapping[this.props.name];

        return(
            <div>
                <center>
                    <curSlide />
                </center>
            </div>
        )
    }
}

If the name of the individual slide components match exactly the slide name in the prop, you can simply create your mapping like this:

this.state = {
    slideMapping: { Slide1, Slide2 }
}

Whether it's more elegant than your current fix, is up to you.

UPDATE: If you want to separate out the mapping, from the SlideContainer you could create a new file called Slides.js with the following:

import Slide1 from './Slide1';
import Slide2 from './Slide2';

export const mapping = { Slide1, Slide2 };

And in your SlideComponent you would do this:

import { mapping } from './Slides';

...

let curSlide = mapping[this.props.name];
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download