Curious what the right way to approach this is:
var Hello = React.createClass({
getInitialState: function() {
return {total: 0, input1:0, input2:0};
},
render: function() {
return (
<div>{this.state.total}<br/>
<input type="text" value={this.state.input1} onChange={this.handleChange} />
<input type="text" value={this.state.input2} onChange={this.handleChange} />
</div>
);
},
handleChange: function(e){
this.setState({ ??? : e.target.value});
t = this.state.input1 + this.state.input2;
this.setState({total: t});
}
});
React.renderComponent(<Hello />, document.getElementById('content'));
Obviously you could create separate handleChange functions to handle each different input, but that's not very nice. Similarly you could create a component just for an individual input, but I wanted to see if there's a way to do it like this.
To pass multiple parameters to onChange in React: Pass an arrow function to the onChange prop. The arrow function will get called with the event object. Call your handleChange function and pass it the event and the rest of the parameters.
I suggest sticking to standard HTML attributes like name
on input
Elements to identify your inputs. Also, you don't need to keep "total" as a separate value in state because it is composable by adding other values in your state:
var Hello = React.createClass({
getInitialState: function() {
return {input1: 0, input2: 0};
},
render: function() {
const total = this.state.input1 + this.state.input2;
return (
<div>{total}<br/>
<input type="text" value={this.state.input1} name="input1" onChange={this.handleChange} />
<input type="text" value={this.state.input2} name="input2" onChange={this.handleChange} />
</div>
);
},
handleChange: function(e) {
this.setState({[e.target.name]: e.target.value});
}
});
React.renderComponent(<Hello />, document.getElementById('content'));
You can use the .bind
method to pre-build the parameters to the handleChange
method.
It would be something like:
var Hello = React.createClass({
getInitialState: function() {
return {input1:0,
input2:0};
},
render: function() {
var total = this.state.input1 + this.state.input2;
return (
<div>{total}<br/>
<input type="text" value={this.state.input1}
onChange={this.handleChange.bind(this, 'input1')} />
<input type="text" value={this.state.input2}
onChange={this.handleChange.bind(this, 'input2')} />
</div>
);
},
handleChange: function (name, e) {
var change = {};
change[name] = e.target.value;
this.setState(change);
}
});
React.renderComponent(<Hello />, document.getElementById('content'));
(I also made total
be computed at render time, as it is the recommended thing to do.)
The onChange
event bubbles... So you can do something like this:
// A sample form
render () {
<form onChange={setField}>
<input name="input1" />
<input name="input2" />
</form>
}
And your setField method might look like this (assuming you're using ES2015 or later:
setField (e) {
this.setState({[e.target.name]: e.target.value})
}
I use something similar to this in several apps, and it's pretty handy.
valueLink/checkedLink
are deprecated from core React, because it is confusing some users. This answer won't work if you use a recent version of React. But if you like it, you can easily emulate it by creating your own Input
component
What you want to achieve can be much more easily achieved using the 2-way data binding helpers of React.
var Hello = React.createClass({
mixins: [React.addons.LinkedStateMixin],
getInitialState: function() {
return {input1: 0, input2: 0};
},
render: function() {
var total = this.state.input1 + this.state.input2;
return (
<div>{total}<br/>
<input type="text" valueLink={this.linkState('input1')} />;
<input type="text" valueLink={this.linkState('input2')} />;
</div>
);
}
});
React.renderComponent(<Hello />, document.getElementById('content'));
Easy right?
http://facebook.github.io/react/docs/two-way-binding-helpers.html
You can even implement your own mixin
You can also do it like this:
...
constructor() {
super();
this.state = { input1: 0, input2: 0 };
this.handleChange = this.handleChange.bind(this);
}
handleChange(input, value) {
this.setState({
[input]: value
})
}
render() {
const total = this.state.input1 + this.state.input2;
return (
<div>
{total}<br />
<input type="text" onChange={e => this.handleChange('input1', e.target.value)} />
<input type="text" onChange={e => this.handleChange('input2', e.target.value)} />
</div>
)
}
If anyone looking for Functional Component Example,
import React, { useState } from "react";
export default function Exapmle() {
const [userState, setUserState] = useState({
firstName: "",
lastName: ""
})
const handleChange = (e)=>{
const value = e.target.value;
setUserState({
...userState,
[e.target.name]: value
});
}
return (
<form>
<label>
First name
<input type="text" name="firstName" value={userState.firstName}
onChange={handleChange}
/>
</label>
<label>
Last name
<input type="text" name="lastName" value={userState.lastName}
onChange={handleChange}
/>
</label>
</form>
);
}
You can use a special React
attribute called ref
and then match the real DOM nodes in the onChange
event using React
's getDOMNode()
function:
handleClick: function(event) {
if (event.target === this.refs.prev.getDOMNode()) {
...
}
}
render: function() {
...
<button ref="prev" onClick={this.handleClick}>Previous question</button>
<button ref="next" onClick={this.handleClick}>Next question</button>
...
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With