Nick Zuber
Nick Zuber

Reputation: 5637

Giving a state to parent component in React

I know you can pass down states and props in React from a parent component to a child component, but is there any way to do this the opposite way?

For example:

Given some child component:

var Child = React.createClass({

  getInitialState: function(){
    return {
      data: ''
    };
  },

  componentDidMount: function(){
    this.setState({data: 'something'});
  },

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

});

and given some parent component:

var Parent = React.createClass({

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

});

Is there any way for me to give Parent the value of the state data from Child?

Upvotes: 1

Views: 1406

Answers (2)

sprjr
sprjr

Reputation: 21

One way to do this is through a 'render props' pattern I was recently introduced to. Remember, this.props.children is really just a way for React to pass things down to a component.

For your example:

var Parent = React.createClass({
  render: function() {
    return (
      <div>
        <Child>
          {(childState) => {
             // render other 'grandchildren' here
          }}
        </Child>
      </div>
    );
  }
});

And then in <Child> render method:

var Child = React.createClass({
  propTypes: {
    children: React.PropTypes.func.isRequired
  },
  // etc
  render () {
    return this.props.children(this.state);
  }
});

This is probably best suited for cases where the <Child /> is responsible for doing something but doesn't really care much at all about the children that would be rendered in its place. The example the react training guys used was for a component that would fetch from Github APIs, but allow the parent to really control what / if anything was rendered with those results.

Upvotes: 2

Matthew Herbst
Matthew Herbst

Reputation: 31983

No.

But yes. But really no.

You cannot "pass" anything from a child to a parent in React. However, there are two solutions you can use to simulate such a passing.

1) pass a callback from the parent to the child

var Parent = React.createClass({
  getInitialState: function() {
    return {
      names: []
    };
  },
  addName: function(name) {
    this.setState({
      names: this.state.names.push(name)
    });
  },
  render: function() {
    return (
      <Child 
        addName={this.addName}
      />
    );
  }
});

var Child = React.createClass({
  props: {
    addName: React.PropTypes.func.isRequired
  },
  handleAddName: function(event) {
    // This is a mock
    event.preventDefault();
    var name = event.target.value;
    this.props.addName(name);
  },
  render: function() {
    return (
      ...
        onClick={this.handleAddName}
      ...
    );
  }
});

The second option is to have a top-level state by using a Flux-style action/store system, such as Reflux or Redux. These basically do the same thing as the above, but are more abstract and make doing so on much larger applications very easy.

Upvotes: 4

Related Questions