0

I have a parent component (App) that holds the state. Inside this component I have some code that manipulates the state through event handlers. So far so good.

However, I need to display the current state inside a child component (ChildComponent). I tried to achieve this by passing the state as a property to the ChildComponent, however I lose the dynamic coupling to the state. Any change to state is not reflected in the child component.

class ChildComponent extends React.Component {
    constructor(props) {
        super(props);
    }

    render () {
        // This should get dynamically updated
        return <div>{this.props.value.toString()}</div>
    }
}


class App extends React.Component {
    constructor(props) {
        super(props);
        this.state = {value: 1};
    }

    // Do stuff here that changes state

    render() {
         return <ChildComponent value={this.state.value} />
    }
}

works now: Updated correct example on codepen

This example is a basic representation of my problem. I think I followed the example of the official docs, and specifically lifting state up. Somehow it does not work though. Could be me misinterpreting the docs (those also happen to be not so good).

edit: maybe having to do with the child component being a class rather than a function?

Roy Prins
  • 2,790
  • 2
  • 28
  • 47
  • How do you update `state`? It should work, check this example - https://codepen.io/anon/pen/gmOzXg – Nick Feb 24 '17 at 00:37
  • Do you use `setState`? `this.setState({value: 2});` or `this.state.value = 2`? – Nick Feb 24 '17 at 00:39
  • The second option. So I need to use the setState method to propagate the state changes to other components? Because it sure works without for just the state on the active component. – Roy Prins Feb 24 '17 at 00:45
  • If you want to call `render()` function you should use `setState`. – Nick Feb 24 '17 at 00:46
  • I updated the codepen and it works. Could you post your comment as an answer, so that I can accept it? For reasons of posterity and karma. – Roy Prins Feb 24 '17 at 00:48

3 Answers3

1

You should not mutate the state of a component directly (this.state.x = this.state.x + 1), but use setState.

See this question for additional info, and what the React docs used to say on the subject.

Community
  • 1
  • 1
Andy_D
  • 4,112
  • 27
  • 19
1

You should use setState. setState always triggers a re-render:

https://codepen.io/anon/pen/gmOzXg

Nick
  • 1,530
  • 2
  • 15
  • 22
  • I learned it is also possible to manually trigger a re-render by calling `this.forceUpdate();`. Might be convenient if you only update a fraction of the state. – Roy Prins Feb 24 '17 at 01:03
  • `Normally you should try to avoid all uses of forceUpdate()`. – Nick Feb 24 '17 at 01:05
  • The reason I was doing that, is because it is a bit complicated to update nested objects within the `state`. I ended up avoiding nested objects in my state. IMO `setState` could really benefit from a function call like `setState('objectProperty.nestedProperty.nestedProperty', newValue)` – Roy Prins Feb 24 '17 at 15:19
0

This works as you expected:

class ChildComponent extends React.Component {
    constructor(props) {
        super(props);
    }

    render () {
        // This should get dynamically updated
        return <div>{this.props.value.toString()}</div>
    }
}


class App extends React.Component {
    constructor(props) {
        super(props);
        this.state = {value: 1};
        this.addOne = this.addOne.bind(this);
    }

    addOne(event){
      this.setState({value: this.state.value+1})
      console.log(this.state.value)
    }

    // Do stuff here that changes state

    render() {
         return (
             <div>
                 <button onClick={this.addOne}>add 1</button>
                 <ChildComponent value={this.state.value} />
             </div>
         )
    }
}

ReactDOM.render(
    <App />,
    document.getElementById('root')
);

You can test it here.

Petr Lazarev
  • 3,102
  • 1
  • 21
  • 20
  • Seems to be identical to the updated CodePen I included with my question ;) – Roy Prins Feb 24 '17 at 02:00
  • Of course, I get your code, improve it and now it works as expected. In your CodePin click on "Add 1" button does not change count. May be you shared some non-final version. – Petr Lazarev Feb 24 '17 at 23:35