あまブログ

ドキドキ......ドキドキ2択クイ〜〜〜〜〜〜〜ズ!!

【React】スプレッド構文の使い方

この記事では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>
    </>
  );
}

【参考】