はじめに
今回は、useStateを使った中級編?として、配列を扱い、
どのように状態の更新をするのかを見ていきます。
useStateの基本的な使い方を知りたい方は、以下の記事で解説していますので、ぜひご参考に!
複数の日付を格納した配列を管理
まずは、以下のコードを書いて、動作を確かめてみます。
onChangeで呼ばれる関数内でアラートを使用して配列の中身を
確認すると分かりますが、画面上では値の変更をしても
配列の中身は変化していないことが分かります。
import React, { useRef, useState } from 'react';
function App(): JSX.Element {
// サンプルデータ
const data = ['2023-09-01', '2023-09-02', '2023-09-03'];
// string型の配列を準備してuseStateの初期値として設定
const [dates, setDates] = useState<string[]>(data);
// 変更があった場合に呼び出される関数
const handleChange = (e: any, index: number) => {
// --------あとでここを変更します------------
};
return (
<>
<div style={{ margin: '30px' }}>
{/* datesの要素分ループして、inputタグを作る */}
{dates.map((item, index) => {
return <input style={{ marginLeft: '10px' }} type="date" defaultValue={item} onChange={(e: any) => handleChange(e, index)} />
})}
</div>
{/* 配列の中身を確認 */}
<div style={{ margin: '50px' }}>{dates.join(' , ')}</div>
</>
);
}
export default App;
これで準備は出来ましたので、ここから配列の操作をしてみます。
この時点では、値を変更してもuseState内のdatesの中身は変化していません。
そのため、onChangeで呼ばれる関数内で配列を更新しなければなりません。
import React, { useRef, useState } from 'react';
function App(): JSX.Element {
// サンプルデータ
const data = ['2023-09-01', '2023-09-02', '2023-09-03'];
// string型の配列を準備してuseStateの初期値として設定
const [dates, setDates] = useState<string[]>(data);
// 変更があった場合に呼び出される関数
const handleChange = (e: any, index: number) => {
// 現在のdatesをコピー(これがないと再レンダリングされない:重要)
const updateDates = [...dates];
// 変更したinputの内容をコピーした配列に上書き
updateDates[index] = e.target.value;
// 上書きした配列でuseStateの更新
setDates(updateDates);
};
return (
<>
<div style={{ margin: '30px' }}>
{/* datesの要素分ループして、inputタグを作る */}
{dates.map((item, index) => {
return <input style={{ marginLeft: '10px' }} type="date" defaultValue={item} onChange={(e: any) => handleChange(e, index)} />
})}
</div>
{/* 配列の中身を確認 */}
<div style={{ margin: '50px' }}>{dates.join(' , ')}</div>
</>
);
}
export default App;
これで、値の変更をしたときも配列の中身が変わることを確認できました!!
配列の後ろに追加したい場合
上で紹介した方法ではなく、日付を変更するたびに要素を追加したい場合もあると思います。
その場合は、スプレッド構文を使うと簡単に記述できます。
import React, { useRef, useState } from 'react';
function App(): JSX.Element {
// サンプルデータ
const data = ['2023-09-01', '2023-09-02', '2023-09-03'];
// string型の配列を準備してuseStateの初期値として設定
const [dates, setDates] = useState<string[]>(data);
// 変更があった場合に呼び出される関数
const handleChange = (e: any) => {
// スプレッド構文を使用して、配列の最後に要素を追加
setDates([...dates, e.target.value])
};
return (
<>
<div style={{ margin: '30px' }}>
{/* 初期値は最後の要素、変更があった場合はhandleChange関数を呼び出す */}
<input type="date" defaultValue={dates[dates.length - 1]} onChange={(e: any) => handleChange(e)} />
</div>
{/* 配列の要素を表示 */}
<div style={{ margin: '50px' }}>{dates.join(' , ')}</div>
</>
);
}
export default App;
備考
今回の解説で書いたコードの中にもう少し説明したいことが、
いくつかありましたので、補足します。
スプレッド構文
スプレッド構文は、「…」のことです。
勉強し始めた時は、書き間違いかな?と思っちゃうやつです。
でも、これがすごく便利なんです。
これは言葉では分かりづらいので、サンプルコードを見てください。
const array = [1, 2, 3]
const tempArray = [4, 5]
console.log([...array, ...tempArray]) // [ 1, 2, 3, 4, 5 ]
console.log([-1, 0, ...array]) // [ -1, 0, 1, 2, 3 ]
これくらいなら、そんなに便利だとは感じないですよね?(便利ではあるけど。。。)
安心してください、スプレッド構文はこんなもんじゃありまっせん。
const obj = {'name': 'ito', age: '24'}
console.log({...obj})
// { name: 'ito', age: '24' }
console.log({...obj, 'age': '32'})
// { name: 'ito', age: '32' }
console.log({...obj, 'foot size': '26cm'})
//{ name: 'ito', age: '24', 'foot size': '26cm' }
このように、オブジェクトのプロパティを変更したり、新しく追加したりできます。
スプレッド構文に慣れると、配列の操作も自由自在です。
joinメソッド
次は、joinメソッドについてです。
このメソッドも非常に便利で、配列の中の値を結合してくれます。
const array = ['hello', 'Tom']
console.log(array.join(', ')) // hello, Tom
const array2 = [1, 3]
console.log(array2.join(2)) // 123
console.log(array.join(array2)) // hello1,3Tom
このように、値の結合がシンプルになります。
数字でも問題ありませんし、配列同士でも問題ありません。
ただし、型には注意しておかないと、後々バグになる可能性もあるので、
型には注意しましょう。
また、配列の操作系メソッドは以下の記事でも紹介していますので、
気になる方は、ご覧ください。
最後に
ここまで読んでいただきありがとうございます。
今回はuseStateで配列データを扱う方法について解説しました。
配列の操作って面倒ですよね。。。
でも思い通りに動かせたときは、すごく嬉しいし、
開発できる機能も増えるのでどんどん使ってみてください!
いっぱいサンプルコードを改造して練習するのが良いと思います!
コメント