Reputation: 6587
In an example of the React docs page Forms, ES6 computed property syntax is used in a method to set the state of the name
property.
handleInputChange(event) {
const target = event.target;
const value = target.type === 'checkbox' ? target.checked : target.value;
const name = target.name;
this.setState({
[name]: value
});
}
Based on my reading of how the computed property works, it seems like the reason it's used is so target.name
can be changed -- is that so? If that's the case it seems like it would just be easier to change it there in setState
rather than changing the value of the name
variable.
I'm new to React and struggling to understand how the computed property syntax is applied in this example. Any help would be greatly appreciated.
Upvotes: 3
Views: 1713
Reputation: 153
Maybe by writing without the ES6 syntax you will understand more what's going on.
The same code would be as below (you could run it in the snippet and see it)
One thing I would tell though is use let
instead of const
simply because variables created with const
constantly point or bind to the same value as long as they "live".
So, using const
here may not let you check and/or uncheck the box, or let you increase/decrease the number.
I hope it helps you understand more.
Thanks
class Reservation extends React.Component {
constructor(props) {
super(props);
this.state = {
isGoing: true,
numberOfGuests: 2
};
this.handleInputChange = this.handleInputChange.bind(this);
}
handleInputChange(event) {
let value;
if(event.target.type==='checkbox'){
value = event.target.checked
}
else {
value = event.target.value
}
this.setState({
[event.target.name]: value
});
}
render() {
return (
<form>
<label>
Is going:
<input
name="isGoing"
type="checkbox"
checked={this.state.isGoing}
onChange={this.handleInputChange} />
</label>
<br />
<label>
Number of guests:
<input
name="numberOfGuests"
type="number"
value={this.state.numberOfGuests}
onChange={this.handleInputChange} />
</label>
</form>
);
}
}
ReactDOM.render(
<Reservation />,
document.getElementById('root')
);
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div id="root"></div>
Upvotes: 0
Reputation: 21844
Why use ES6 computed property syntax for object setState?
The computed property syntax allows you to set the key of an object dynamically.
In the case of setState
, it allows you to handle different properties of the state with a single setState
, and so to reuse the same event handler function on different inputs.
So instead of:
class Reservation extends React.Component {
constructor(props) {
super(props);
this.state = {
isGoing: true,
numberOfGuests: 2
};
this.handleIsGoingChange = this.handleIsGoingChange.bind(this);
this.handleNumberOfGuestsChange = this.handleNumberOfGuestsChange.bind(this);
}
// a first handler, for isGoing
handleIsGoingChange(event) {
const target = event.target;
const value = target.checked;
this.setState({
isGoing: value
});
}
// a second handler, for numberOfGuests
handleNumberOfGuestsChange(event) {
const target = event.target;
const value = target.value;
this.setState({
numberOfGuests: value
});
}
render() {
return (
<form>
<label>
Is going:
<input
name="isGoing"
type="checkbox"
checked={this.state.isGoing}
onChange={this.handleIsGoingChange} />
</label>
<br />
<label>
Number of guests:
<input
name="numberOfGuests"
type="number"
value={this.state.numberOfGuests}
onChange={this.handleNumberOfGuestsChange} />
</label>
</form>
);
}
}
You can shorten it like this:
class Reservation extends React.Component {
constructor(props) {
super(props);
this.state = {
isGoing: true,
numberOfGuests: 2
};
this.handleInputChange = this.handleInputChange.bind(this);
}
// a single handler, for isGoing and numberOfGuests
handleInputChange(event) {
const target = event.target;
const value = target.type === 'checkbox' ? target.checked : target.value;
const name = target.name;
this.setState({
[name]: value
});
}
render() {
return (
<form>
<label>
Is going:
<input
name="isGoing"
type="checkbox"
checked={this.state.isGoing}
onChange={this.handleInputChange} />
</label>
<br />
<label>
Number of guests:
<input
name="numberOfGuests"
type="number"
value={this.state.numberOfGuests}
onChange={this.handleInputChange} />
</label>
</form>
);
}
}
Upvotes: 7
Reputation: 8023
If you don't use the computed property syntax, your function would always set the name
property instead of the computed value from event.target.name
, which is what you want. Your state would always look like this:
console.log(this.state);
// -> { name: 'some value' }
Upvotes: 1
Reputation: 213
When you wrap a key with array square brackets it will get the variable name as a key.
If you doesn't the key will be string. So...
let name = 'id';
let obj = { //let obj = {
[name]:1 // id: 1
}; //};
Upvotes: 3
Reputation: 138267
Cause you don't want to set the "name" property, but the property which name is stored in name.
var name = "test";
// these are all equal:
this.setState({ [name]: 1 })
this.setState({ ["test"]: 1 })
this.setState({ test: 1 })
Upvotes: 1