🍇
state変数に配列を持つ場合の更新方法
Reactのstateで保持しているオブジェクトを更新する際には、直接そのオブジェクトを変更するのではなく、新しいオブジェクトを作る、もしくは既存のオブジェクトのコピーを作って、setXXX(newObject)
で更新する必要があります。
stateに配列を保持する場合も同様です。
const [list, setList] = useState([0]);
const ngHandler1 = () => {
// NG
list[0] = 10;
}
const ngHandler2 = () => {
// NG
list.push(10);
setList(list);
}
const okHandler = () => {
// OK
const newList = f(list); // どうにかして新しいリストを作る
setList(newList);
}
新しい配列を作る方法はいくつかありますが、公式ドキュメントにどのようにすれば良いかがまとまっていました。
以下に新しい配列を作る方法についてまとめます(ほぼ翻訳&要約です)。
詳しくはこちらの公式ドキュメントにまとまっています。
要素を追加したいとき
スプレッド構文を利用します。
const [list, setList] = useState([0]);
const handler = () => {
setList([...list, 10]);
}
上記では、元のリストの末尾に「10」という要素を追加した新しい配列を作り、stateを更新しています。
以下のようにすることで、リストの先頭に要素を追加することもできます。
const handler = () => {
setList([10, ...list]);
}
要素を削除したいとき
filter
を利用します。
削除したい要素を取り除き、新しい配列を作ります。
const [list, setList] = useState(["a", "b", "c"]);
const handler = () => {
setList(list.filter(item => item !== "b"))
}
上記のようにすることで、b
という要素を取り除くことができます。
要素を変更したいとき、置き換えたいとき
map
を利用します。
以下では一部の要素を変更します。
const [list, setList] = useState([
{id: 0, type: "comic", count: 10},
{id: 1, type: "magazine", count: 5},
{id: 2, type: "novel", count: 22},
]);
const handler = () => {
setList(list.map(item => {
if(item.type === "comic") {
return item;
} else {
return {
...item,
count: item.count + 1
}
}
}))
}
以下では一部の要素を置き換えます。
const [list, setList] = useState(["a", "b", "c"]);
const handler = () => {
setList(list.map(item => {
if(item !== "b") {
return item.toUpperCase();
}
return item;
}))
}
要素を特定の位置に挿入したいとき
先頭でも末尾でもない位置に要素を挿入したい場合は、スプレッド構文とslice
を利用します。
以下では、a
とc
の間にb
を挿入します。
const [list, setList] = useState(["a", "c"]);
const handler = () => {
const insertAt = 1;
setList([
...list.slice(0, insertAt),
"b",
...list.slice(insertAt)
])
}
その他の変更方法
スプレッド構文やmapやfilterだけではできないこともいくつかあります。例えば、配列を反転したり並び替える操作です。
JavaScriptのreverse
やsort
は元の配列を直接変更するため、stateの更新には利用できません。
ただし、最初に配列をコピーして、コピーした配列に操作を行うことはできます。
以下では配列の中身を反転します。
const [list, setList] = useState(["a", "b", "c"]);
const handler = () => {
const newList = [...list];
newList.reverse();
setList(newList)
}
Discussion