Ad

ReactJS Component State Does Not Change As Expected

- 1 answer

I created a Container class and an InnerElement class. Where the Container wraps the InnerElements. It is necessary to show just a single InnerElement at a given time.

The problem appears, when I change to another InnerElement. Interestingly when I create a console.log it displays the changed element but it is not rendered. Could someone give me a hint please, thanks in advance!

Container class:

import React from 'react';

export default class Container extends React.Component {

    constructor(props) {
        super(props);

        this.changeElement = this.changeElement.bind(this);

        this.state = {
            currentElement: 0,
        }
    }

    changeElement() {
        const nextElement = this.state.currentElement + 1;
        this.setState({currentElement: nextElement});
    }

    render() {
        const element = this.props.children[this.state.currentElement];
        // In the console log the next (correct) element is shown
        console.log(element);

        return (
            <div>
                {element}
                <button onClick={this.changeElement}>next element</button>
            </div>
        );
    }
}

Here the InnerElement class:

import React from 'react';
export default class InnerElement extends React.Component {

    constructor(props) {
        super(props);

        this.state = {
            name: props.name ? props.name : "test"
        }
    }

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

And here my Container with InnerElement call:

<Container>
    <InnerElement name="A" />
    <InnerElement name="B" />
    <InnerElement name="C" />
    <InnerElement name="D" />
</Container>

I also discovered, that it works, when I use in the InnerElement this.props.name instead of the state.

Ad

Answer

React have trouble determining your children is changing with your setState because you are dynamically modifying the children. To help React do this, you can add a key to your InnerElement:

<Container>
  <InnerElement key="A" name="A" />
  <InnerElement key="B" name="B" />
  <InnerElement key="C" name="C" />
  <InnerElement key="D" name="D" />
</Container>
Ad
source: stackoverflow.com
Ad