モダンJavaScriptの基礎から始める挫折しないためのReact入門 60日コース | モダンJavaScript基礎 - DAY 9:分割代入・Spread構文

React 60日で身につけるReact
スポンサーリンク
スポンサーリンク
  1. DAY 9:分割代入・Spread構文 前半 ― 「取り出す」と「コピーする」を一気に強くする回
  2. 分割代入 ― 「欲しいものだけ取り出す」技術
    1. オブジェクトの分割代入とは
    2. プロパティ名と違う変数名で受け取りたい場合
  3. 配列の分割代入 ― 「順番で取り出す」技術
    1. 配列の分割代入とは
    2. Reactでよく使う「useStateの分割代入」
  4. Spread構文とコピー・一部更新の基本パターン
    1. Spread構文とは ― 「中身を展開する」記法
    2. オブジェクトコピーの基本
    3. 一部の値を変更する基本パターン
  5. DAY 9:分割代入・Spread構文 前半のまとめ
  6. DAY 9:分割代入・Spread構文 中盤 ― 「Reactで使う形」にぐっと近づける時間
  7. オブジェクトの分割代入を「Reactのprops目線」で理解する
    1. オブジェクトの分割代入の復習
    2. Reactコンポーネントのpropsでの分割代入
  8. 配列の分割代入を「useState目線」で深く理解する
    1. 配列の分割代入の復習
    2. useStateと配列の分割代入
  9. Spread構文で「コピー+一部更新」をReactのState更新に結びつける
    1. 配列コピーとState更新のつながり
    2. オブジェクトコピーとState更新のつながり
    3. 一部の値を変更するときの基本テンプレート
  10. DAY 9:分割代入・Spread構文 中盤のまとめ
  11. DAY 9:分割代入・Spread構文 後半 ― 「State更新の型」を身体に染み込ませる
  12. オブジェクトの分割代入とSpread構文を「フォーム更新」でつなげる
    1. オブジェクトの分割代入で「欲しい値だけ取り出す」
    2. Spread構文で「フォームの一部だけ更新する」
  13. 配列の分割代入とSpread構文を「リスト更新」でつなげる
    1. 配列の分割代入で「状態+更新関数」をセットで扱う
    2. Spread構文で「配列に要素を追加する」
    3. 一部の値を変更する:オブジェクト配列の更新
  14. 分割代入・Spread構文を「安全なState更新の型」としてまとめる
    1. なぜ「コピーしてから更新する」のか
    2. 分割代入とSpread構文の「型」をまとめる
    3. セキュリティ・安全性の視点から見たState更新
  15. DAY 9:分割代入・Spread構文 後半のまとめ

DAY 9:分割代入・Spread構文 前半 ― 「取り出す」と「コピーする」を一気に強くする回

DAY 9では、ReactのState更新で非常に重要になる 分割代入Spread構文(スプレッド構文) を扱います。 前半では、次の学習項目を中心に進めていきます。

  • オブジェクトの分割代入
  • 配列の分割代入
  • Spread構文
  • 配列コピー
  • オブジェクトコピー
  • 一部の値を変更する

ここまで学んできた「オブジェクト」「配列」「map・filter・find」と強く結びつく内容なので、 ステップバイステップで、初心者向けにかみ砕いて説明していきます。

分割代入 ― 「欲しいものだけ取り出す」技術

オブジェクトの分割代入とは

まずは オブジェクトの分割代入 から始めます。 分割代入は、オブジェクトの中から「欲しいプロパティだけを、変数として取り出す」ための書き方です。

通常の書き方だと、次のようになります。

const product = {
  name: 'Tシャツ',
  price: 1200,
  stock: 10,
};

const name = product.name;
const price = product.price;
const stock = product.stock;

console.log(name);  // 'Tシャツ'
console.log(price); // 1200
console.log(stock); // 10
JavaScript

これを分割代入を使うと、次のように短く書けます。

const product = {
  name: 'Tシャツ',
  price: 1200,
  stock: 10,
};

const { name, price, stock } = product;

console.log(name);  // 'Tシャツ'
console.log(price); // 1200
console.log(stock); // 10
JavaScript

ここで起きていることをステップで整理すると、

  1. const { name, price, stock } = product; と書きます。
  2. productオブジェクトのnamepricestockプロパティを、それぞれ同名の変数に取り出します。
  3. 結果として、namepricestockという3つの変数が使えるようになります。

重要ポイント:

  • 「オブジェクトから欲しいプロパティだけを取り出す」ための書き方です。
  • Reactコンポーネントの引数(props)や、Stateオブジェクトから値を取り出すときに頻繁に使われます。

プロパティ名と違う変数名で受け取りたい場合

ときどき、「プロパティ名と違う名前の変数で受け取りたい」ことがあります。 その場合は、次のように書きます。

const product = {
  name: 'Tシャツ',
  price: 1200,
  stock: 10,
};

const { name: productName, price: productPrice } = product;

console.log(productName);  // 'Tシャツ'
console.log(productPrice); // 1200
JavaScript
  • name: productNameproduct.nameproductName という変数に取り出す
  • price: productPriceproduct.priceproductPrice という変数に取り出す

Reactでは、propsから受け取った値を、 コンポーネント内で分かりやすい名前に変えたいときに使うことがあります。

配列の分割代入 ― 「順番で取り出す」技術

配列の分割代入とは

次に、配列の分割代入 を見ていきます。 配列の分割代入は、「配列の中身を、順番に変数として取り出す」ための書き方です。

通常の書き方だと、次のようになります。

const numbers = [10, 20, 30];

const first = numbers[0];
const second = numbers[1];
const third = numbers[2];

console.log(first);  // 10
console.log(second); // 20
console.log(third);  // 30
JavaScript

これを分割代入を使うと、次のように書けます。

const numbers = [10, 20, 30];

const [first, second, third] = numbers;

console.log(first);  // 10
console.log(second); // 20
console.log(third);  // 30
JavaScript

ここで起きていることをステップで整理すると、

  1. const [first, second, third] = numbers; と書きます。
  2. numbers[0]first に、numbers[1]second に、numbers[2]third に代入されます。
  3. 結果として、3つの変数が使えるようになります。

重要ポイント:

  • 配列の分割代入は「順番」で取り出します。
  • オブジェクトの分割代入は「プロパティ名」で取り出します。

Reactでよく使う「useStateの分割代入」

Reactでは、配列の分割代入が useState で頻繁に登場します。

const [count, setCount] = useState(0);
JSX
  • useState(0) は、[現在の値, 更新関数] という配列を返します。
  • const [count, setCount] = useState(0); で、
    • count → 現在の値
    • setCount → 更新関数 という2つの変数に分割代入しています。

この形はReactを書くうえでほぼ必須なので、 「配列の分割代入=useStateの書き方」としてセットで覚えておくと自然です。

Spread構文とコピー・一部更新の基本パターン

Spread構文とは ― 「中身を展開する」記法

ここからがDAY 9の核心である Spread構文(スプレッド構文) です。 ...(ドット3つ)を使って、配列やオブジェクトの「中身を展開する」記法です。

まずは配列から見ていきます。

配列コピーの基本

const numbers = [1, 2, 3];

const copied = [...numbers];

console.log(copied);  // [1, 2, 3]
JavaScript
  • ...numbers が「numbersの中身を展開する」という意味です。
  • [...numbers] で、「同じ要素を持つ新しい配列」を作っています。
  • 元の numbers は変更されません。

重要ポイント:

  • Spread構文は「コピーを作る」ための強力な道具です。
  • ReactのState更新では、「元の配列を直接書き換えず、新しい配列を作る」ことが非常に重要です。

配列に要素を追加する

Spread構文を使うと、「コピー+追加」が簡単に書けます。

const numbers = [1, 2, 3];

const withFour = [...numbers, 4];

console.log(withFour); // [1, 2, 3, 4]
JavaScript
  • [...numbers, 4] で、「元の要素+新しい要素」を持つ配列を作っています。
  • 元の numbers はそのままです。

Reactでは、「新しいアイテムを追加した配列」をStateとしてセットするときに、この形がよく使われます。

オブジェクトコピーの基本

次に、オブジェクトのSpread構文を見ていきます。

const product = {
  name: 'Tシャツ',
  price: 1200,
  stock: 10,
};

const copiedProduct = { ...product };

console.log(copiedProduct);
/*
{
  name: 'Tシャツ',
  price: 1200,
  stock: 10,
}
*/
JavaScript
  • { ...product } で、「同じプロパティと値を持つ新しいオブジェクト」を作っています。
  • 元の product は変更されません。

重要ポイント:

  • オブジェクトのSpread構文も「コピーを作る」ための道具です。
  • ReactのState更新では、「元のオブジェクトを直接書き換えず、新しいオブジェクトを作る」ことが重要です。

一部の値を変更する基本パターン

Spread構文の真価は、「コピーしつつ、一部だけ上書きする」場面で発揮されます。

オブジェクトの一部更新

const product = {
  name: 'Tシャツ',
  price: 1200,
  stock: 10,
};

const updatedProduct = {
  ...product,
  price: 1500,
};

console.log(updatedProduct);
/*
{
  name: 'Tシャツ',
  price: 1500,
  stock: 10,
}
*/
JavaScript

ここで起きていることをステップで整理すると、

  1. ...product で「元のオブジェクトのコピー」を作ります。
  2. その上から price: 1500 を上書きします。
  3. 結果として、「価格だけ変わった新しいオブジェクト」ができます。
  4. 元の product はそのまま残ります。

このパターンは、ReactのState更新で頻出します。

配列の一部更新(導入)

配列の一部更新は少し複雑ですが、基本の考え方は同じです。 例えば、「先頭の要素だけを変えたい」場合を考えます。

const numbers = [1, 2, 3];

const updatedNumbers = [0, ...numbers.slice(1)];

console.log(updatedNumbers); // [0, 2, 3]
JavaScript
  • numbers.slice(1) で「2番目以降の要素」を取り出します。
  • [0, ...numbers.slice(1)] で、「先頭だけ新しい値+残りは元の値」という配列を作っています。

Reactでは、より実践的には「map+条件分岐+Spread構文」でオブジェクト配列の一部を更新することが多いですが、 ここでは「Spread構文でコピーしつつ、一部だけ変える」という発想を持っておくことが大事です。

DAY 9:分割代入・Spread構文 前半のまとめ

DAY 9の前半では、

  • オブジェクトの分割代入
    • const { name, price } = product; のように、欲しいプロパティだけを変数として取り出す
    • プロパティ名と違う変数名で受け取る書き方(name: productName)も確認したこと
  • 配列の分割代入
    • const [first, second] = numbers; のように、順番で取り出す
    • ReactのuseStateが配列の分割代入の代表例であること
  • Spread構文(スプレッド構文)
    • 配列コピー:const copied = [...numbers];
    • 配列に要素追加:const withFour = [...numbers, 4];
    • オブジェクトコピー:const copiedProduct = { ...product };
    • オブジェクトの一部更新:const updatedProduct = { ...product, price: 1500 };
  • 「元の配列・オブジェクトを直接書き換えず、新しいものを作る」という発想が、ReactのState更新で非常に重要であること

を確認しました。

中盤・後半では、

  • オブジェクト配列に対するSpread構文の使い方
  • mapと組み合わせた「一部の要素だけ更新する」パターン
  • Reactコンポーネント内での具体的なState更新の例

などを通して、 分割代入とSpread構文が「Reactでは必須級」と言われる理由を、 より実感としてつかんでいく流れになります。


DAY 9:分割代入・Spread構文 中盤 ― 「Reactで使う形」にぐっと近づける時間

DAY 9の中盤では、前半で触れた

  • オブジェクトの分割代入
  • 配列の分割代入
  • Spread構文
  • 配列コピー
  • オブジェクトコピー
  • 一部の値を変更する

を、ReactのState更新でそのまま使える形に寄せて整理していきます。 ここでも理解しやすいように「前半・中盤・後半」の3つに分けて、連続した流れとして説明していきます。

オブジェクトの分割代入を「Reactのprops目線」で理解する

オブジェクトの分割代入の復習

まずは、オブジェクトの分割代入をもう一度確認します。

const product = {
  name: 'Tシャツ',
  price: 1200,
  stock: 10,
};

const { name, price, stock } = product;

console.log(name);  // 'Tシャツ'
console.log(price); // 1200
console.log(stock); // 10
JavaScript
  • const { name, price, stock } = product; で、
    • product.namename
    • product.priceprice
    • product.stockstock という3つの変数に取り出しています。

ここまでは「オブジェクトから欲しいプロパティを取り出す」基本形です。

Reactコンポーネントのpropsでの分割代入

Reactでは、この分割代入が コンポーネントの引数(props) でよく使われます。

function ProductCard(props) {
  const { name, price, stock } = props;

  return (
    <div>
      <h3>{name}</h3>
      <p>価格:{price}円</p>
      <p>在庫:{stock}個</p>
    </div>
  );
}
JSX
  • props はオブジェクトです。
  • props.nameprops.priceprops.stock を、分割代入でそれぞれの変数に取り出しています。

さらに、引数のところで直接分割代入する書き方もよく使われます。

function ProductCard({ name, price, stock }) {
  return (
    <div>
      <h3>{name}</h3>
      <p>価格:{price}円</p>
      <p>在庫:{stock}個</p>
    </div>
  );
}
JSX
  • function ProductCard({ name, price, stock }) { ... } で、
    • props.namename
    • props.priceprice
    • props.stockstock という形で受け取っています。

重要ポイント:

  • オブジェクトの分割代入は、「propsから欲しい値だけを取り出す」ための定番パターンです。
  • 引数で分割代入する書き方は、Reactコンポーネントで非常によく使われます。

配列の分割代入を「useState目線」で深く理解する

配列の分割代入の復習

配列の分割代入は、「配列の中身を順番に変数として取り出す」ための書き方でした。

const numbers = [10, 20, 30];

const [first, second, third] = numbers;

console.log(first);  // 10
console.log(second); // 20
console.log(third);  // 30
JavaScript
  • numbers[0]first
  • numbers[1]second
  • numbers[2]third

という対応になっています。

useStateと配列の分割代入

Reactでは、配列の分割代入が useState で必ず登場します。

const [count, setCount] = useState(0);
JSX

ここで起きていることをステップで整理すると、

  1. useState(0) は、内部的に「配列」を返します。
    • 例:[現在の値, 更新関数]
  2. const [count, setCount] = useState(0); で、
    • 配列の1番目(現在の値) → count
    • 配列の2番目(更新関数) → setCount に分割代入しています。
  3. 結果として、
    • count → 現在の状態
    • setCount → 状態を更新するための関数 という2つの変数が使えるようになります。

重要ポイント:

  • 配列の分割代入は、「ReactのuseStateの書き方」とセットで覚えると自然です。
  • 「左側の変数名は自由に決められる」ので、意味の分かりやすい名前を付けることが大事です。

例えば、次のような形もよく使われます。

const [products, setProducts] = useState([]);
const [keyword, setKeyword] = useState('');
const [isOpen, setIsOpen] = useState(false);
JSX
  • products → 商品一覧の状態
  • setProducts → 商品一覧を更新する関数
  • keyword → 検索キーワードの状態
  • setKeyword → 検索キーワードを更新する関数
  • isOpen → モーダルの開閉状態
  • setIsOpen → モーダルの開閉状態を更新する関数

このように、「状態」と「更新関数」をペアで扱う」 という感覚が、配列の分割代入と一緒に身についていきます。

Spread構文で「コピー+一部更新」をReactのState更新に結びつける

配列コピーとState更新のつながり

前半で見た「配列コピー」を、ReactのState更新目線で整理します。

const numbers = [1, 2, 3];

const copied = [...numbers];

console.log(copied);  // [1, 2, 3]
JavaScript

Reactでは、次のような形で使われます。

const [numbers, setNumbers] = useState([1, 2, 3]);

const addNumber = () => {
  const newNumbers = [...numbers, 4];
  setNumbers(newNumbers);
};
JSX

ここで起きていることをステップで整理すると、

  1. numbers が現在の配列の状態です。
  2. const newNumbers = [...numbers, 4]; で、
    • 元の numbers の中身をコピーし、
    • 末尾に 4 を追加した新しい配列を作っています。
  3. setNumbers(newNumbers); で、その新しい配列をStateとしてセットしています。
  4. 元の numbers は直接書き換えられていません。

重要ポイント:

  • Spread構文は、「元の配列を壊さず、新しい配列を作る」ための道具です。
  • ReactのState更新では、「直接書き換えず、新しい値を渡す」ことが基本ルールです。

オブジェクトコピーとState更新のつながり

オブジェクトのコピーも、ReactのState更新と強く結びつきます。

const product = {
  name: 'Tシャツ',
  price: 1200,
  stock: 10,
};

const copiedProduct = { ...product };
JavaScript

Reactでは、次のような形で使われます。

const [product, setProduct] = useState({
  name: 'Tシャツ',
  price: 1200,
  stock: 10,
});

const updatePrice = () => {
  const updatedProduct = {
    ...product,
    price: product.price + 500,
  };

  setProduct(updatedProduct);
};
JSX

ここで起きていることをステップで整理すると、

  1. product が現在のオブジェクトの状態です。
  2. const updatedProduct = { ...product, price: product.price + 500 }; で、
    • 元の product の中身をコピーし、
    • price だけを上書きした新しいオブジェクトを作っています。
  3. setProduct(updatedProduct); で、その新しいオブジェクトをStateとしてセットしています。
  4. 元の product は直接書き換えられていません。

重要ポイント:

  • Spread構文は、「コピー+一部更新」を1行で書ける強力なパターンです。
  • ReactのState更新では、「元のオブジェクトを直接書き換えない」ことが非常に重要です。

一部の値を変更するときの基本テンプレート

オブジェクトの一部更新のテンプレートを、もう一度整理しておきます。

const updated = {
  ...original,
  changedKey: newValue,
};
JavaScript
  • ...original → 元のオブジェクトのコピー
  • changedKey: newValue → 一部のプロパティだけを上書き

ReactのState更新では、次のような形が頻出します。

setUser({
  ...user,
  name: '新しい名前',
});

setForm({
  ...form,
  email: 'new@example.com',
});
JSX

この形を「テンプレート」として覚えておくと、State更新が一気に書きやすくなります。

DAY 9:分割代入・Spread構文 中盤のまとめ

DAY 9の中盤では、

  • オブジェクトの分割代入を「Reactのprops目線」で整理し、
    • function Component({ foo, bar }) { ... } という書き方が定番であること
  • 配列の分割代入を「useState目線」で深く理解し、
    • const [value, setValue] = useState(initialValue); という形がReactで必須級であること
  • Spread構文を「State更新」と結びつけて、
    • 配列コピー+追加:const newArray = [...array, newItem];
    • オブジェクトコピー+一部更新:const newObj = { ...obj, key: newValue }; という基本パターンを確認したこと
  • 「元の配列・オブジェクトを直接書き換えず、新しいものを作る」という発想が、ReactのState更新のルールと直結していること

を整理しました。

後半では、

  • オブジェクト配列に対するSpread構文の使い方
  • mapと組み合わせた「一部の要素だけ更新する」パターン
  • 実際のReactコンポーネントでの具体的なState更新例

を通して、 分割代入とSpread構文が「Reactでは必須級」と言われる理由を、 より実践的なコードの形で体感していく流れになります。


DAY 9:分割代入・Spread構文 後半 ― 「State更新の型」を身体に染み込ませる

DAY 9の後半では、これまで扱ってきた

  • オブジェクトの分割代入
  • 配列の分割代入
  • Spread構文
  • 配列コピー
  • オブジェクトコピー
  • 一部の値を変更する

を、ReactのState更新の「型」として使えるレベルまで一気にまとめていきます。 ここでも理解しやすいように「前半・中盤・後半」の3つに分けて、連続した流れとして説明していきます。

オブジェクトの分割代入とSpread構文を「フォーム更新」でつなげる

オブジェクトの分割代入で「欲しい値だけ取り出す」

まずは、オブジェクトの分割代入をReactの中でどう使うかを、フォームの例で見ていきます。

function ProfileForm({ user }) {
  const { name, email } = user;

  return (
    <div>
      <p>名前:{name}</p>
      <p>メール:{email}</p>
    </div>
  );
}
JSX
  • user はオブジェクト(例:{ name: 'Alice', email: 'alice@example.com' })です。
  • const { name, email } = user; で、user.nameuser.email をそれぞれ変数に取り出しています。
  • JSXの中では、nameemailとしてシンプルに扱えます。

このように、「propsから欲しいプロパティだけを取り出す」 のが、オブジェクトの分割代入の基本的な使い方です。

Spread構文で「フォームの一部だけ更新する」

次に、フォームの入力値をStateで管理する例を見ていきます。

import { useState } from 'react';

function ProfileForm() {
  const [form, setForm] = useState({
    name: '',
    email: '',
  });

  const handleChangeName = (e) => {
    setForm({
      ...form,
      name: e.target.value,
    });
  };

  const handleChangeEmail = (e) => {
    setForm({
      ...form,
      email: e.target.value,
    });
  };

  const { name, email } = form;

  return (
    <div>
      <input
        value={name}
        onChange={handleChangeName}
        placeholder="名前"
      />
      <input
        value={email}
        onChange={handleChangeEmail}
        placeholder="メールアドレス"
      />
    </div>
  );
}
JSX

ここで起きていることをステップで整理すると、

  1. form はオブジェクトで、nameemailという2つのプロパティを持っています。
  2. handleChangeNameでは、
    • ...form で「今のフォーム状態のコピー」を作り、
    • name: e.target.valuenameだけを上書きした新しいオブジェクトを作っています。
  3. handleChangeEmailでは、
    • 同じく ...form でコピーを作り、
    • email: e.target.valueemailだけを上書きしています。
  4. setFormには「新しいオブジェクト」を渡していて、元のformは直接書き換えていません。
  5. JSXの中では、const { name, email } = form; で分割代入し、value={name}value={email}として使っています。

重要ポイント:

  • オブジェクトの分割代入 → 「状態オブジェクトから欲しい値だけ取り出す」
  • Spread構文+一部更新 → 「状態オブジェクトの一部だけを安全に更新する」

この2つが組み合わさることで、Reactのフォーム処理が非常に書きやすくなります。

配列の分割代入とSpread構文を「リスト更新」でつなげる

配列の分割代入で「状態+更新関数」をセットで扱う

配列の分割代入は、ReactのuseStateで必ず登場します。

const [todos, setTodos] = useState([]);
JSX
  • todos → 現在のToDoリスト(配列)の状態
  • setTodos → ToDoリストを更新するための関数

この「状態+更新関数」のペアを、配列の分割代入で受け取っています。

Spread構文で「配列に要素を追加する」

次に、ToDoリストに新しいタスクを追加する例を見ていきます。

function TodoApp() {
  const [todos, setTodos] = useState([
    { id: 1, title: '買い物に行く' },
    { id: 2, title: 'Reactの勉強をする' },
  ]);

  const addTodo = () => {
    const newTodo = {
      id: Date.now(),
      title: '新しいタスク',
    };

    const newTodos = [...todos, newTodo];

    setTodos(newTodos);
  };

  return (
    <div>
      <button onClick={addTodo}>タスクを追加</button>
      <ul>
        {todos.map((todo) => (
          <li key={todo.id}>{todo.title}</li>
        ))}
      </ul>
    </div>
  );
}
JSX

ここで起きていることをステップで整理すると、

  1. todos は「オブジェクト配列」としてToDoリストを表しています。
  2. addTodoでは、
    • newTodo という新しいタスクオブジェクトを作り、
    • const newTodos = [...todos, newTodo]; で、
      • 元のtodosの中身をコピーし、
      • 末尾にnewTodoを追加した新しい配列を作っています。
  3. setTodos(newTodos); で、その新しい配列をStateとしてセットしています。
  4. 元のtodosは直接書き換えられていません。
  5. JSXでは、todos.map(...)でリスト表示しています。

重要ポイント:

  • Spread構文は、「配列に要素を追加した新しい配列」を作るための定番パターンです。
  • ReactのState更新では、「元の配列を直接書き換えず、新しい配列を渡す」ことが基本ルールです。

一部の値を変更する:オブジェクト配列の更新

次に、「特定のタスクのタイトルだけを変更する」例を見ていきます。

function TodoApp() {
  const [todos, setTodos] = useState([
    { id: 1, title: '買い物に行く' },
    { id: 2, title: 'Reactの勉強をする' },
  ]);

  const updateTodoTitle = (id, newTitle) => {
    const newTodos = todos.map((todo) => {
      if (todo.id === id) {
        return {
          ...todo,
          title: newTitle,
        };
      } else {
        return todo;
      }
    });

    setTodos(newTodos);
  };

  return (
    <div>
      <ul>
        {todos.map((todo) => (
          <li key={todo.id}>
            {todo.title}
            <button
              onClick={() =>
                updateTodoTitle(todo.id, todo.title + '(更新)')
              }
            >
              タイトルを更新
            </button>
          </li>
        ))}
      </ul>
    </div>
  );
}
JSX

ここで起きていることをステップで整理すると、

  1. todos は「オブジェクト配列」としてToDoリストを表しています。
  2. updateTodoTitleでは、
    • todos.map((todo) => { ... }) で、各タスクを1つずつ処理しています。
    • todo.id === id のときだけ、
      • { ...todo, title: newTitle } で「タイトルだけ変えた新しいオブジェクト」を作っています。
    • それ以外のタスクは、元のtodoをそのまま返しています。
  3. mapの結果として、「1件だけタイトルが更新された新しい配列newTodos」ができます。
  4. setTodos(newTodos); で、その新しい配列をStateとしてセットしています。
  5. 元のtodosや各todoオブジェクトは直接書き換えられていません。

重要ポイント:

  • 「オブジェクト配列の一部だけを更新する」定番パターンは、
    • map+条件分岐+Spread構文(コピー+一部更新) です。
  • ReactのState更新では、このパターンが本当に頻繁に登場します。

分割代入・Spread構文を「安全なState更新の型」としてまとめる

なぜ「コピーしてから更新する」のか

ここまで何度も出てきた、

  • const newArray = [...array, newItem];
  • const newObj = { ...obj, key: newValue };
  • const newList = list.map(item => item.id === id ? { ...item, ... } : item);

というパターンは、単に「書き方が便利だから」ではなく、 安全で予測可能なState更新のために必要な型です。

理由を整理すると次のとおりです。

  1. 元の値を直接書き換えると、どこで何が変わったか追いにくくなるから
    • 他の処理が同じオブジェクトや配列を参照している場合、意図しない影響が出ることがあります。
  2. Reactは「新しい参照」をもとに再レンダリングを判断するから
    • 新しいオブジェクトや配列を渡すことで、「状態が変わった」とReactが正しく認識できます。
  3. テストやデバッグのときに、「変更前」と「変更後」を比較しやすくなるから
    • コピー+一部更新のスタイルは、変更箇所が明確で追いやすいです。

分割代入とSpread構文の「型」をまとめる

ここまでの内容を、「型」としてまとめると次のようになります。

オブジェクトの分割代入(props・stateから取り出す)

function Component({ foo, bar }) {
  // foo, bar をそのまま使える
}
JSX
const { name, email } = user;

配列の分割代入(useState)

const [value, setValue] = useState(initialValue);
JSX

配列コピー+追加

const newArray = [...array, newItem];
setArray(newArray);
JSX

オブジェクトコピー+一部更新

const newObj = {
  ...obj,
  key: newValue,
};
setObj(newObj);
JSX

オブジェクト配列の一部更新

const newList = list.map((item) =>
  item.id === targetId
    ? { ...item, key: newValue }
    : item
);

setList(newList);
JSX

この5つの型を「手で書ける」ようになると、ReactのState更新はほぼ怖くなくなります。

セキュリティ・安全性の視点から見たState更新

最後に、セキュリティ・安全性の視点からも少し触れておきます。

  • 外部入力(ユーザーの操作)に応じて状態を更新するときは、値の妥当性を意識すること
    • 例えば、価格がマイナスにならないようにする、在庫数が不自然な値にならないようにする、といったチェックが必要になる場面があります。
  • 元の状態を直接書き換えないことで、予期しない副作用を防ぎやすくなること
    • 他の処理が同じオブジェクトや配列を参照している場合でも、「新しい状態」を渡すスタイルなら影響範囲を限定しやすいです。
  • 状態の変化が明確であることは、結果的にユーザーにとっても安全で分かりやすいUIにつながること
    • 「何が変わったか」がコード上で追いやすいと、バグや不正な挙動を減らしやすくなります。

DAY 9:分割代入・Spread構文 後半のまとめ

DAY 9の後半では、

  • オブジェクトの分割代入を「props」や「フォーム状態」から値を取り出す場面で確認したこと
  • 配列の分割代入を「useState」の形と結びつけて、状態+更新関数のペアとして理解したこと
  • Spread構文を使った「配列コピー+追加」「オブジェクトコピー+一部更新」を、ReactのState更新の具体的なコードとして見たこと
  • オブジェクト配列の一部更新を、map+条件分岐+Spread構文という定番パターンで整理したこと
  • 「元の値を直接書き換えず、新しい値を渡す」ことが、安全で予測可能なState更新のために重要であること
  • 分割代入とSpread構文が、ReactのState更新の「型」として身体に染み込むと、アプリの規模が大きくなっても怖くなくなること

をまとめました。

ここまでで、Reactの「データと状態」を扱うためのJavaScript基礎はかなり強くなっています。 この先は、コンポーネント分割やイベント処理、より複雑な状態管理へと進みながら、 今日学んだ「分割代入・Spread構文の型」を、実際のアプリの中で自然に使えるようにしていく流れになります。

タイトルとURLをコピーしました