APatrick
APatrick

Reputation: 13

How can I set the state of my parent component from the child component when using react-router?

I am working on a React project where the user will be prompted a series of questions, the answers to which will be combined as an object to be saved.

The parent component contains several children.

for example--

<Route path="Parent" component={Parent}>
    <Route path="Child1" component={Child1} />
    <Route path="Child2" component={Child2} />
    <Route path="Child3" component={Child3} />
    <IndexRoute component={Child1} />
</Route>

The parent will have an initial state of empty values ex. (this.state={value1:"", value2:""})

How can I pass data from the child to the parent (and props from the parent to the children) when using {this.props.children}?

Upvotes: 0

Views: 123

Answers (2)

Vlatko Vlahek
Vlatko Vlahek

Reputation: 1899

In order for a parent to get data from its child back, you need to pass a callback function as a property to that child.

callbackFunction(data) {
    // do something
}

<ChildComponent parentCallback={this.callbackFunction} />

Then you can use the prop inside the child component to send data back to its parent, which will then use the callback function to do something with it.

const x = ["a", "b", "c", "d"];
this.props.parentCallback(x);

Check the following article for more details: https://medium.com/@ruthmpardee/passing-data-between-react-components-103ad82ebd17

Another option is to use a state container like Redux. In this scenario your child component would dispatch the value to a state, and this state is being listened to by its parent, which will re-render when state changes. This is a solution for more complex scenarios

Upvotes: 1

jered
jered

Reputation: 11571

Instead of using the component prop to render your child routes, use the render prop. This allows you to have a function return the component that you want to render, instead of simply accepting the class itself. It looks like this:

<Route path="Parent" component={Parent}>
    <Route path="Child1" render={() => {<Child1 someProp={foo} />}} />
    <Route path="Child2" render={() => {<Child2 someProp={bar} />}} />
    <Route path="Child3" render={() => {<Child3 someProp={baz} />}} />
    <IndexRoute component={Child1} />
</Route>

Why do it this way instead? Well, as you can see, now you can pass props to the rendered children (in this example, someProp). And now that you can pass props to children, it is trivial to use callbacks to modify parent state from the children.

More info on the render prop here.

Upvotes: 3

Related Questions