この記事ではReactにおけるスプレッド構文の使い方を解説します。
Reactにおいて、スプレッド構文は主にstateが保持するオブジェクトや配列を更新する際に使われます。
1. オブジェクトのスプレッド構文
以下はスプレッド構文を使っていない例。
Reactではstateのオブジェクトを直接変更することは非推奨なので、setPerson()でfirstName, lastName, ageを全て書く必要がある。
import { useState } from 'react';
export default function Form() {
const [person, setPerson] = useState({
firstName: 'ichoro',
lastName: 'suzuki',
age: 8
});
function handleFirstNameChange(e) {
setPerson({
firstName: e.target.value,
lastName: person.lastName, // ここが冗長
age: person.age // ここが冗長
});
}
function handleLastNameChange(e) {
setPerson({
firstName: person.firstName, // ここが冗長
lastName: e.target.value,
age: person.age // ここが冗長
});
}
function handleAgeChange(e) {
setPerson({
firstName: person.firstName, // ここが冗長
lastName: person.lastName, // ここが冗長
age: e.target.value
});
}
return (
<>
<label>
First name:
<input
value={person.firstName}
onChange={handleFirstNameChange}
/>
</label>
<label>
Last name:
<input
value={person.lastName}
onChange={handleLastNameChange}
/>
</label>
<label>
Age:
<input
value={person.age}
onChange={handleAgeChange}
/>
</label>
<p>
{person.firstName}{' '}
{person.lastName}{' '}
({person.age})
</p>
</>
);
}
これを、スプレッド構文を使って書くと以下のようになる。
import { useState } from 'react';
export default function Form() {
const [person, setPerson] = useState({
firstName: 'ichoro',
lastName: 'suzuki',
age: 8
});
function handleFirstNameChange(e) {
setPerson({
...person, // スッキリ
firstName: e.target.value
});
}
function handleLastNameChange(e) {
setPerson({
...person, // スッキリ
lastName: e.target.value
});
}
function handleAgeChange(e) {
setPerson({
...person, // スッキリ
age: e.target.value
});
}
// 省略
}
さらにComputed property namesを使うとイベントハンドラが一つで済む。
import { useState } from 'react';
export default function Form() {
const [person, setPerson] = useState({
firstName: 'ichoro',
lastName: 'suzuki',
age: 8
});
function handleChange(e) {
setPerson({
...person,
[e.target.name]: e.target.value // Computed property names
});
}
return (
<>
<label>
First name:
<input
name="firstName"
value={person.firstName}
onChange={handleChange}
/>
</label>
<label>
Last name:
<input
name="lastName"
value={person.lastName}
onChange={handleChange}
/>
</label>
<label>
Age:
<input
name="age"
value={person.age}
onChange={handleChange}
/>
</label>
<p>
{person.firstName}{' '}
{person.lastName}{' '}
({person.age})
</p>
</>
);
}
ネストしたオブジェクトの場合
import { useState } from 'react';
export default function Form() {
const [person, setPerson] = useState({
name: 'Ichiro Suzuki',
profile: {
age: 8,
city: 'Seattle',
hobby: 'soccer',
}
});
function handleNameChange(e) {
setPerson({
...person,
name: e.target.value
});
}
function handleAgeChange(e) {
setPerson({
...person,
profile: {
...person.profile,
age: e.target.value
}
});
}
function handleCityChange(e) {
setPerson({
...person,
profile: {
...person.profile,
city: e.target.value
}
});
}
function handleHobbyChange(e) {
setPerson({
...person,
profile: {
...person.profile,
hobby: e.target.value
}
});
}
return (
<>
<label>
Name:
<input
value={person.name}
onChange={handleNameChange}
/>
</label>
<label>
Age:
<input
value={person.profile.age}
onChange={handleAgeChange}
/>
</label>
<label>
City:
<input
value={person.profile.city}
onChange={handleCityChange}
/>
</label>
<label>
Hobby:
<input
value={person.profile.hobby}
onChange={handleHobbyChange}
/>
</label>
<p>
{person.name} is {person.profile.age} years old, lives in {person.profile.city}, and likes {person.profile.hobby}.
</p>
</>
);
}
2. 配列のスプレッド構文
stateの配列もオブジェクトと同様に直接編集してはいけないので、スプレッド構文を使って新しい配列を作成して、それをstateに設定する。
import { useState } from 'react';
let nextId = 0;
export default function List() {
const [name, setName] = useState('');
const [foods, setFoods] = useState([]);
return (
<>
<h1>Foods:</h1>
<input
value={name}
onChange={e => setName(e.target.value)}
/>
<button onClick={() => {
setFoods([
...foods,
{ id: nextId++, name: name }
]);
setName('');
}}>Add</button>
<ul>
{foods.map(food => (
<li key={food.id}>{food.name}</li>
))}
</ul>
</>
);
}
【参考】