Signup/Sign In
Ask Question
Not satisfied by the Answer? Still looking for a better solution?

What's the right way to pass form element state to sibling/parent elements?

Suppose I have a React class P, which renders two child classes, C1 and C2.
C1 contains an input field. I'll refer to this input field as Foo.
My goal is to let C2 react to changes in Foo.
I've come up with two solutions, but neither of them feels quite right.

First solution:

Assign P a state, state.input.
Create an onChange function in P, which takes in an event and sets state.input.
Pass this *onChange to C1 as a props, and let C1 bind this.props.onChange to the onChange of Foo.
This works. Whenever the value of Foo changes, it triggers a setState in P, so P will have the input to pass to C2.

But it doesn't feel quite right for the same reason: I'm setting the state of a parent element from a child element. This seems to betray the design principle of React: single-direction data flow.
Is this how I'm supposed to do it, or is there a more React-natural solution?

Second solution:

Just put Foo in P.

But is this a design principle I should follow when I structure my app—putting all form elements in the render of the highest-level class?

Like in my example, if I have a large rendering of C1, I really don't want to put the whole render of C1 to render of P just because C1 has a form element.

How should I do it?
by

2 Answers

espadacoder11
You should learn Redux and ReactRedux library.It will structure your states and props in one store and you can access them later in your components .
RoliMishra
With React >= 16.3 you can use ref and forwardRef, to gain access to child's DOM from its parent. Don't use old way of refs anymore.
Here is the example using your case :

import React, { Component } from 'react';

export default class P extends React.Component {
constructor (props) {
super(props)
this.state = {data: 'test' }
this.onUpdate = this.onUpdate.bind(this)
this.ref = React.createRef();
}

onUpdate(data) {
this.setState({data : this.ref.current.value})
}

render () {
return (
<div>
<C1 ref={this.ref} onUpdate={this.onUpdate}/>
<C2 data={this.state.data}/>
</div>
)
}
}

const C1 = React.forwardRef((props, ref) => (
<div>
<input type='text' ref={ref} onChange={props.onUpdate} />
</div>
));

class C2 extends React.Component {
render () {
return <div>C2 reacts : {this.props.data}</div>
}
}
See Refs and ForwardRef for detailed info about refs and forwardRef.

Login / Signup to Answer the Question.