3

I would like to render a component from a list of subcomponents:

I have a container that renders a menu on the left side of the screen, and sections on the right. The menu items represent the sections, and when the user clicks on an item in the menu, the selected section appears on the right side of the screen.

In trying to do this with React, I ended up with this code (greatly simplified from the real case, to make this shorter, but should be enough to send the intent to the reader):

class SectionContainer extends React.Component {
    constructor(props) {
        super(props)

        this.sections = [
            <SettingsSection
                user={ this.props.user }
            />
        ];

        this.state = {
            selectedSection: 0
        }
    }

    selectSection(index) {
        this.setState({ selectedSection: index });
    }

    render() {
        return (
            <div>
                { this.renderMenu() }
                { this.renderSection() }
            </div>
        );
    }

    renderMenu() {
        let items = [];

        for (var i = 0; i < this.sections.length; i++) {
            items.push(this.sections[i].getMenuEntry());
        }

        return (
            <SectionMenu
                items={ items }
                selectSection={ this.selectSection.bind(this) }
                selectedSection={ this.state.selectedSection }
            />
        );
    }

    renderSection() {
        return this.sections[this.state.selectedSection];
    }
}

class SectionMenu extends React.Component {
    render() {
        return (
            <div>
                { _.map(this.props.items, (item, index) => this.renderSectionItem(item, index)) }
            </div>
        );
    }

    renderSectionItem(item, index) {
        return (
            <SectionItem 
                { ...item }
                onClick={ this.selectSection(index) }
                selectedSection={ this.props.selectedSection == index }
            />
        );
    }

    selectSection(index) {
        this.props.selectSection(index);
    }
}

class SectionItem extends ReactComponent {
    render() {
        return <div>...</div>
    }
}

class Section extends React.Component {
    getMenuEntry() {
        return {
            title: this.getTitle(),
            body: this.getBody(),
        }
    }
}

class SettingsSection extends Section {
    getTitle() {
        return 'Title';
    }

    getBody() {
        return [
            'Line 1',
            'Line 2',
            'Line 3',
        ]
    }

    render() {
        return (
            <div>...</div>
        );
    }
}

However, it looks like I can't obtain instances of React components in a list and simply call methods, or return them on render methods, etc. It looks like they are not regular instances of classes.

How can this behavior be accomplished in React? (I come from a Python background, so I may also have the wrong mindset when working with React, which could be getting in the way.)

jpmelos
  • 3,283
  • 3
  • 23
  • 30
  • if you want to render a variable, example ```const Component = (props) => (
    ...
    )``` you cant ```render() { return Component }``` instead you will need to ```render() { return }``` see sample https://jsfiddle.net/69z2wepo/78146/
    – Rei Dien May 09 '17 at 00:14

1 Answers1

0

You can reach React element's method via refs API.

Also read this answer: React.js - access to component methods

But I think you better do it differently: create a container component, which will render child components: menu and section. It should contain a state of selected item and render corresponding section. You can pass container method to menu child so it could change it's parent state (selected item).

All static data (titles, body, desc etc) should be stored in some model (object or array of objects). Container will pass data from this model down to its children.

Community
  • 1
  • 1
GProst
  • 9,229
  • 3
  • 25
  • 47