Reactjs - How to pass values from child component to grand-parent component?

The most straightforward way is to pass updateState functions as far down the tree as they need to go. Ideally, your grandchild component is thought of as completely separate from the grandparent component... though that quickly becomes tedious.

That's what React Redux is for. It creates a global state object with a publish/subscribe model. (The publish/subscribe model is somewhat abstracted away through a "connect" wrapper.) You can dispatch actions from anywhere, to anywhere. Actions trigger "reducers", which transform the global state, and React reacts to the modified state by re-rendering components (in a surprisingly efficient way).

For small programs, Redux can be overkill. If you really do just have the grandparent/parent/grandchild in your model, just pass the updateState functions. As your program grows, try replacing them with Redux. It can be hard to learn (especially since IMHO the standard tutorials are simply awful), but it's the intended solution to the general problem you're describing.


You can pass the update function to the grand child by props, just pass it again from the child component.

class App extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      data: 'Initial data...'
    }
    this.updateState = this.updateState.bind(this);
  }

  updateState(who) {
    this.setState({data: `Data updated from ${who}`})
  }

  render() {
    return (
      <div>
        Parent: {this.state.data}
        <Child update={this.updateState}/>
      </div>
    )
  }
}

class Child extends React.Component {
  render() {
    return (
      <div>
        Child component
        <button onClick={() => this.props.update('child')}>
          CLICK
        </button>
        <GrandChild update={this.props.update}/>
      </div>
    );
  }
}

class GrandChild extends React.Component {
  render() {
    return (
      <div>
        Grand child component
        <button onClick={() => this.props.update('grand child')}>
          CLICK
        </button>
      </div>
    );
  }
}
ReactDOM.render(<App />, document.getElementById('root'))
<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>
<div id="root"></div>