I'm new developing for React and clearly I'm struggling in how to pass data through components. I have created an example on CodePen to try to understand the flow. The example is just an example of a return a value from a modal to the main level.
I have these levels of hierarchy:
Inside my main component I have a span that I would like to update when the text inside the input field is typed.
I'm using props to pass callbacks and return the value that I need. So, Is there a better way to pass those changes to my Main level?
PS: I saw a lot of examples here on StackOverflow, but I couldn't see this example without Redux or Flux.
My code:
class Main extends React.Component { constructor(props) { super(props); this.state = { text: '' } this.onUpdateLabel = this.onUpdateLabel.bind(this); } onUpdateLabel(value) { this.setState({ text: value }); } render() { let value = this.state.text != '' ? this.state.text : 'Waiting...'; return ( <div> <h1>Main</h1> <span class='label'>{value}</span> <hr /> <Modal onUpdateLabel={this.onUpdateLabel} /> </div> ); } } class Modal extends React.Component { constructor(props) { super(props); } render() { this.props.text = 'Inside Component'; return ( <div> <h2>Modal</h2> <Form onUpdateLabel={this.props.onUpdateLabel} /> </div> ) } } class Form extends React.Component { constructor(props) { super(props); this.state = { text: '' } this.onClickButton = this.onClickButton.bind(this); this.onUpdateText = this.onUpdateText.bind(this); } onUpdateText(e) { this.setState({ text: e.target.value }); } onClickButton() { this.props.onUpdateLabel(this.state.text); } render() { return ( <div> <h3>Form</h3> <input type='text' placeholder='Type something' onChange={this.onUpdateText} /> <button onClick={this.onClickButton}>Click</button> </div> ); } } ReactDOM.render( <Main />, document.getElementById('app') );
<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="app"></div>
You could use the Context but as it is stated in the doc:
It is an experimental API and it is likely to break in future releases of React.
If you decide to still use it, you would write something like that:
class Main extends React.Component {
static childContextTypes = { // Define the child context
onUpdateLabel: PropTypes.func,
}
constructor(props) {
super(props);
this.state = {
text: ''
}
this.onUpdateLabel = this.onUpdateLabel.bind(this);
}
onUpdateLabel(e) {
this.setState({ text: e.target.value });
}
getChildContext(){ // Return the wanted context
return {
onUpdateLabel: this.onUpdateLabel,
}
}
render() {...}
}
and in your Form
class Form extends React.Component {
static contextTypes = { // Define the available context
onUpdateLabel: PropTypes.func,
}
constructor(props) {
super(props);
this.state = {
text: ''
}
this.onClickButton = this.onClickButton.bind(this);
this.onUpdateText = this.onUpdateText.bind(this);
}
onUpdateText(e) {
this.setState({ text: e.target.value });
}
onClickButton() { // Retrieve it from context instead of props
this.context.onUpdateLabel(this.state.text);
}
render(){...}
}
You define the context in the main element, and use it in one of the children.
Your method is alright you were calling
e.target.value
where it's not present
onUpdateLabel(text) {
this.setState({ text: text });
}
class Main extends React.Component { constructor(props) { super(props); this.state = { text: '' } this.onUpdateLabel = this.onUpdateLabel.bind(this); } onUpdateLabel(text) { this.setState({ text: text }); } render() { let value = this.state.text != '' ? this.state.text : 'Waiting...'; return ( <div> <h1>Main</h1> <span class='label'>{value}</span> <hr /> <Modal onUpdateLabel={this.onUpdateLabel} /> </div> ); } } class Modal extends React.Component { constructor(props) { super(props); } render() { this.props.text = 'Inside Component'; return ( <div> <h2>Modal</h2> <Form onUpdateLabel={this.props.onUpdateLabel} /> </div> ) } } class Form extends React.Component { constructor(props) { super(props); this.state = { text: '' } this.onClickButton = this.onClickButton.bind(this); this.onUpdateText = this.onUpdateText.bind(this); } onUpdateText(e) { this.setState({ text: e.target.value }); } onClickButton() { this.props.onUpdateLabel(this.state.text); } render() { return ( <div> <h3>Form</h3> <input type='text' placeholder='Type something' onChange={this.onUpdateText} /> <button onClick={this.onClickButton}>Click</button> </div> ); } } ReactDOM.render(<Main />, document.getElementById('app'));
<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="app"></div>
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.