React公式ページで学んでみた⑧（備忘録）

# はじめに
初めまして！
エンジニアになって数年、今まで本を読むだけでしたが、もっとプライベートで楽しみながら成長したい！自分が学んだ足跡を残していきたい！と思い記事を書きました！
最終的には自在に開発できるようになりたいと思っています。:triumph:
いろいろな記事を参考にさせてもらっています。:bow_tone2:
その中でもこれってどういう意味？とかつまづいたところを念入りに書いていこうかと思います。:fist:

# 今回の目的
前回の続きです。今回も「インタラクティビティの追加」。被る部分もあると思いますが、後で振りかえって深掘りするきっかけになるのが理想です。細かく書くと大変なのであっさりめ。

https://qiita.com/mr_noppo/items/fae25e7241febee4799f

# 使用したものや事前準備
・Macbook Pro
・Visual Studio Code

# 主に参考にさせていただいた記事
https://ja.react.dev/learn/updating-arrays-in-state

# stateの配列の更新方法
オブジェクトでも直接の変更は再レンダーされなかったが、配列もオブジェクトと同等なため同様のことが言える。
更新するには、配列の書き換えではなく新しい配列にコピーしてset関数を呼ぶ。

## 要素追加
[NG]
下記の場合、オブジェクト内部の変更のため再レンダが発生しない。
```react
      <button onClick={() => {
        artists.push({
          id: nextId++,
          name: name,
        });
      }}>Add</button>
```
[OK]
スプレット構文を使用しset関数を使用することで新しい配列の作成と再レンダを行う。
```react
      <button onClick={() => {
        setArtists([
          ...artists,
          { id: nextId++, name: name }
        ]);
      }}>Add</button>
```
※見本はnextIdをletで管理しているがこれは本来避けるべきなので真似しないようにしたい。

## 要素削除
filterを使用する。新しい配列を返す。
artist.idの方がスナップショット。 a => a.idがfilter、
```react
     <button onClick={() => {
       setArtists(
         artists.filter(a =>
           a.id !== artist.id
        )
       );
    }}>
```

## 配列内のオブジェクト変換
mapを使用する。
ある条件に沿って、配列内のオブジェクトを返すパターン
```react
  function handleClick() {
    const nextShapes = shapes.map(shape => {
      if (shape.type === 'square') {
        // 四角形だったらそのまま返す
        return shape;
      } else {
        // それ以外は値を変更
        return {
          ...shape,
          y: shape.y + 50,
        };
      }
    });
    // 新しい配列を返してset関数を動かし再レンダー
    setShapes(nextShapes);
  }
```

## 配列内の要素の置換
mapを使用する。
インデックスを使って、配列の値を置き換えるパターン
```react
  function handleIncrementClick(index) {
    const nextCounters = counters.map((c, i) => {
      if (i === index) {
        // liタグの例で押したkeyIndexと同じ値をインクリメントする
        return c + 1;
      } else {
        // それ以外はそのまま
        return c;
      }
    });
    // 新しい配列を返してset関数を動かし再レンダー
    setCounters(nextCounters);
  }
```

## 配列の挿入
sliceを使う。sliceは半開区間である。
```react
  function handleClick() {
    const insertAt = 1;
    const nextArtists = [
      // この場合は0以上1未満のインデックス配列をコピー
      ...artists.slice(0, insertAt),
      // 新しい値の挿入
      { id: nextId++, name: name },
      // 
      ...artists.slice(insertAt)
    ];
    setArtists(nextArtists);
    setName('');
  }
```

## 配列へのその他の変更
配列を逆順にしたり、ソートしたりするのはmapやfilterではできない。
そのため、スプレット構文で配列をコピーしてからreverse()やsort()を使用しsetする。
```react
  function handleClick() {
    const nextList = [...list];
    nextList.reverse();
    setList(nextList);
  }
```

## 配列はシャロコピー
配列はシャローコピーのため、配列内がオブジェクトなら同じ配列をコピーしていた時に配列同士で影響が出る。

```react
const [myList, setMyList] = useState(initialList);
const [yourList, setYourList] = useState(initialList);

const myNextList = [...myList];
const artwork = myNextList.find(a => a.id === artworkId);
artwork.seen = nextSeen; // この場合、initialList内のseenが変更されるため、yourListの値も変更されてしまう
setMyList(myNextList);
```

mapでオブジェクトを再生成し更新する。
```react
setMyList(myList.map(artwork => {
  if (artwork.id === artworkId) {
    // オブジェクトを再生成し変更するところをオーバーライドするやり方
    return { ...artwork, seen: nextSeen };
  } else {
    return artwork;
  }
}));
```


# 終わりに
配列内のオブジェクトについてはまだ混乱します。

# 次
https://qiita.com/mr_noppo/items/f0345efa4eb697f32522