JavaScript | 配列・オブジェクト:実務パターン – フラグ更新

JavaScript JavaScript
スポンサーリンク

フラグ更新とは何か

フラグ更新は「オブジェクトや配列の中で、真偽値(true/false)や状態を表す小さな印(flag)を安全に切り替える」操作です。ここが重要です:配列やネスト構造では“直接書き換え”を避け、非破壊更新(イミュータブル)で新インスタンスを返すのが基本。1件だけの更新、複数件の一括更新、条件でのトグル(反転)など、定番パターンを覚えるとミスなく書けます。


1件のフラグを更新する(ID指定の基本パターン)

該当IDだけ非破壊で置き換える

const items = [
  { id: 1, name: "A", active: false },
  { id: 2, name: "B", active: true }
];

function setActiveById(list, id, value) {
  return list.map(item =>
    item.id === id ? { ...item, active: value } : item
  );
}

const next = setActiveById(items, 1, true);
// id=1 の active が true に、他はそのまま
JavaScript

ここが重要です:mapで“該当だけスプレッドで差し替え、その他は元の参照を保つ”のが最短で安全。UIの差分検知も安定します。

トグル(反転)を簡潔に書く

function toggleActiveById(list, id) {
  return list.map(item =>
    item.id === id ? { ...item, active: !item.active } : item
  );
}
JavaScript

ここが重要です:!(論理否定)で反転。undefined時は !undefined が true なので注意。未定義に既定値を与えたいなら !(item.active ?? false) を使います。


1件だけを「選択中」にする(単一選択の確実な更新)

一件だけ選択、それ以外は解除

function selectOnly(list, id) {
  return list.map(item => ({ ...item, selected: item.id === id }));
}

// 使い方
const next = selectOnly(items, 2);
// id=2 が selected:true、他は false
JavaScript

ここが重要です:分岐を一本化して“選択対象は true、それ以外は false”と明示する。既存値を参照して部分的に切り替えるより、ルールで全体を決めるほうがバグが減ります。

既定値を合わせて安全化

function selectOnlySafe(list, id) {
  return list.map(item => ({
    ...item,
    selected: item.id === id ? true : false
  }));
}
JavaScript

ここが重要です:selected が存在しない要素にも確実に boolean を与える設計が安全。後続処理が単純になります。


複数件をまとめて更新する(条件一括・範囲操作)

条件で一括ON/OFF

function setArchivedByPredicate(list, pred, value) {
  return list.map(item => pred(item) ? { ...item, archived: value } : item);
}

// 例:qty >= 10 をアーカイブ
const next = setArchivedByPredicate(items, it => it.qty >= 10, true);
JavaScript

ここが重要です:更新条件を関数(pred)に切り出すと再利用しやすい。テストしやすく、要件変更にも強いです。

一覧の「全選択/全解除」

function setAllSelected(list, value) {
  return list.map(item => ({ ...item, selected: value }));
}

const allOn  = setAllSelected(items, true);
const allOff = setAllSelected(items, false);
JavaScript

ここが重要です:ループ内で分岐せず“全件同じ値”を入れると読みやすく、速度も安定します。


タイムスタンプやメタ情報を付ける(更新の痕跡を残す)

更新時に時刻を記録する

function setFlagWithStamp(list, id, key, value) {
  const now = new Date().toISOString();
  return list.map(item =>
    item.id === id ? { ...item, [key]: value, [`${key}At`]: now } : item
  );
}

// 例:active を true にしつつ activeAt を記録
const next = setFlagWithStamp(items, 1, "active", true);
JavaScript

ここが重要です:監査やUIの“更新直後だけハイライト”などに有効。キーから派生した時刻フィールドで汎用化すると使い回せます。

カウンタや履歴を増やす

function incrementToggleCount(list, id) {
  return list.map(item =>
    item.id === id
      ? { ...item, active: !item.active, toggledCount: (item.toggledCount ?? 0) + 1 }
      : item
  );
}
JavaScript

ここが重要です:?? 0 で既定値を与え、“初回でも動く”設計に。未定義へ加算すると NaN になる落とし穴を避けられます。


ネスト構造のフラグ更新(オブジェクト内・配列内)

ネストオブジェクトのフラグを安全に更新

const state = {
  user: { profile: { city: "Tokyo" }, flags: { vip: false } }
};

const next = {
  ...state,
  user: {
    ...state.user,
    flags: { ...state.user.flags, vip: true }
  }
};
JavaScript

ここが重要です:更新したい階層ごとにスプレッドで“新しくする”。一段でも省くと参照共有が残り、他所で予期せず変わる原因になります。

ネスト配列の要素フラグ更新

function setItemFlag(state, id, key, value) {
  const nextItems = (state.items ?? []).map(it =>
    it.id === id ? { ...it, [key]: value } : it
  );
  return { ...state, items: nextItems };
}
JavaScript

ここが重要です:配列は map、欠損には ?? [] を使う。読み取りでは ?.、既定値では ?? を併用して“落ちないコード”にします。


UI向けのトグルパターン(押下→一時ON、単一ON)

一時ON(押している間だけ)

function setPressed(list, id, pressed) {
  return list.map(it => ({ ...it, pressed: it.id === id ? pressed : false }));
}
JavaScript

ここが重要です:押下中の対象だけ true、他は false。単一選択の応用で、瞬間的な状態管理にも使えます。

ステータス遷移(OFF→ON→DISABLED など)

function cycleStatusById(list, id) {
  const order = ["off", "on", "disabled"];
  const rank = new Map(order.map((s, i) => [s, i]));
  return list.map(it => {
    if (it.id !== id) return it;
    const i = rank.get(it.status) ?? 0;
    const next = order[(i + 1) % order.length];
    return { ...it, status: next };
  });
}
JavaScript

ここが重要です:状態の順序表を作って“次へ送る”。分岐だらけの if/else より読みやすく、拡張にも強い。


よくある落とし穴と回避策(重要ポイントの深掘り)

破壊的更新で共有状態を壊す

直接 items[i].active = true のように書くと、他の参照が持つ配列やオブジェクトにも影響します。必ず“新インスタンスで置換”する(map+スプレッド)。

未定義・nullでトグルが意図通りにならない

!undefined は true。未定義を“false相当”として扱う設計なら良いですが、厳密に制御したいなら !(value ?? false) として既定値を付ける。

ID型の揺れで一致しない

文字列”2″と数値2は===では別。保管時に String(id) へ正規化する、比較前に型を揃えるなど、ブレを無くす。

複数場所に同じフラグを持つ

同じ意味のフラグが複数箇所に散らばると不整合(片側だけ更新)が起きます。正規化(entities)して“唯一の更新源”に集約し、表示側は参照にする。


すぐ使えるレシピ(現場でそのまま使える)

単一選択を保証する

const selectOnly = (list, id) =>
  list.map(item => ({ ...item, selected: item.id === id }));
JavaScript

IDで真偽を設定・トグル

const setFlagById = (list, id, key, value) =>
  list.map(x => (x.id === id ? { ...x, [key]: value } : x));

const toggleFlagById = (list, id, key) =>
  list.map(x => (x.id === id ? { ...x, [key]: !(x[key] ?? false) } : x));
JavaScript

条件一括(例:price>=1000だけ on)

const setFlagBy = (list, key, pred, value) =>
  list.map(x => (pred(x) ? { ...x, [key]: value } : x));
JavaScript

まとめ

フラグ更新の核心は「非破壊更新で該当だけ置換し、仕様で“全体のルール”を決めて一括適用する」ことです。1件の更新は map+スプレッドが最短、単一選択は“対象だけtrue、他はfalse”を明示。一括更新は条件関数で柔軟に、トグルは未定義への既定値を忘れずに。ネストでは階層ごとにコピーして安全に、監査用に時刻や回数を付けると実務に強い。これらを押さえれば、初心者でも短く、読みやすく、バグの少ないフラグ更新が書けます。

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