0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

stateでオブジェクトを扱う #9

Posted at

📢 このシリーズについて

このシリーズは、React公式ドキュメント( https://ja.react.dev/ )を(できるだけ)全て読み、学んだことやコード例、自分なりの補足をまとめていくチャレンジの記録です。

目的

  • Reactの基礎〜応用を公式の正しい情報で体系的に理解する
  • 自分の言葉でアウトプットして知識を定着させる

このシリーズでは、ただ内容をなぞるのではなく、「自分がReactを使っていても気づかなかった事実や落とし穴」 を重点的にまとめます。

読んだときに「へぇ、そうなんだ!」となったポイントは必ず記録します!

目次 - 本記事で取り扱う内容

  • JavaScriptの値は2種類ある
  • stateは常に読み取り専用で
  • スプレッド構文の注意点
  • それでも全部書きたくないやい!!

🗂 基本情報



📌 内容

stateはどんなJavaScriptの値でも保持できる。よく見るのは数値や真偽値だが、当然オブジェクトも保持できる。ただし、stateでオブジェクトを扱うときには注意点がある。それは、stateで保持するオブジェクトを直接書き換えず、都度新しいオブジェクトを作成しstateにセットする必要があるということだ。

JavaScriptの値は2種類ある

JavaScriptで取り扱う値といえば、数値や文字列、真偽値などが真っ先に浮かぶがこれらは “ イミュータブル(不変, immutable)” に分類できる。

これは文字通り、値が変わらない「読み取り専用」の値と言える。この値の再レンダーをトリガするには値の置き換えが必要。

イミュータブルな値に対し、 “ ミュータブル(可変, mutable)” な値とは、書き換え可能なものである。オブジェクトや配列、関数がこれにあたる。

置き換える処理は以下の様なものがある。

// stateでオブジェクトの保持を宣言
const [ obj,setObj ] = useState({ x: 0, y: 0 });

// オブジェクトの値を書き換える処理
obj.x = 5;

これでオブジェクト自体の値を書き換えることはできた。

この操作を “ ミューテーション(mutation) “ という。

しかし、これはバッドプラクティスだ。ミュータブルな値もイミュータブルな値のように取り扱うべきだ。

stateは常に読み取り専用で

これまでの話を簡潔にまとめると、「stateで保持するすべてのJavaScriptオブジェクトは書き換えず、読み取り専用として扱うべき」ということになる。

stateで保持するオブジェクトの更新は以下のように記述する。

なお、ここでは例として、マウスの座標を保持したいとする。

// stateの定義
const [ obj, setObj ] = useState({ x: 0, y: 0 });
// stateの更新
onClick={e => {
	setObj({
		x: e.clientX,
		y: e.clientY
	});
});

つまり、すべてのプロパティを定義しオブジェクト全体を生成して渡す必要があるということだ。

ただ、毎回すべてを書かなければならいわけではない。スプレッド構文という便利な記法がある。

以下は押下したキーを3つ目のプロパティに保存するコード。

// stateの定義
const [ obj, setObj ] = useState({
	prop1: 'A',
	prop2: 'B',
	prop3: 'C',
	prop4: 'D',
});
// stateの更新
onClisck={e => {
	setObj({
		...obj,
		prop3: e.key,
	});
});

このように記述することで、prop3(更新するプロパティ)以外はもともとあったプロパティをそのまま利用できる。

スプレッド構文の注意点

スプレッド構文が展開できるのは1つ下のレベルの内容のみです。つまり、ネストされているプロパティはそのレベルでさらにスプレッド構文こ記述する必要がある。

// stateの定義
const [ obj, setObj ] = useState({
	prop1: 'A',
	prop2: 'B',
	prop3: 'C',
	nest: {
		nest1: 'N',
		nest2: 'E',
		nest3: 'S',
		nest4: 'T',
	}
});
// stateの更新
onClisck={e => {
	setObj({
		...obj,
		nest: {
			...obj.nest,
			nest3: e.key,
		}
	});
});

単に一つ下のレベルでスプレッド構文を使っているだけで使用方法は同じだ。

それでも全部書きたくないやい!!

Immerっていうライブラリを使えば全部書かなくてもよくなる。

ミューテート型の構文で記述するだけでよく、内部でそのほかのプロパティをコピーしてくれる。ありがたいね。

Immerを使うには以下の手順を行う。

// 1. 依存関係のインストール
npm install use-immer

// 2. インポート
import { useState } from 'react';  <- これは削除
import { useImmer } from 'use-immer'  <- これに書き換える



🚀 宣伝コーナー

個人開発もやっています🍃

ぜひ一度触ってみてください!

1. CAN I DO THIS

📜概要

🌟 「この問題、私に解ける?」がすぐ分かる! 🌟

CAN I DO THIS は、問題(文章/画像)をポンっと入れるだけで、「解くのに必要な前提知識」を瞬時に可視化するツールです💡

🛡 前提知識がないまま無理に挑んで、時間と体力をムダに消耗…

そんな経験、もうしなくてOK。

必要な知識が足りているか、すぐ判断できます!

✨ 主な機能

  • 問題を貼るだけ → 必要知識リスト+学習ルート自動生成
  • 前提 → 派生が一目で分かる依存関係グラフ
  • 登録不要&無料(広告視聴で利用可能)

🔗 今すぐ試す

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?