ステート変数：分割代入（Destructuring assignment）でのステート宣言の書き方

Kindle書籍「Next.jsでつくるフルスタックアプリ 後編　三好アキ著」を読んでの備忘録。

### １．ステート変数宣言のシンプルな書き方

各データにつき一つのステートを用意するシンプルな書き方。
ここではname, email, そしてpasswordというステート変数を宣言している。

```js
const Register = () => {
  //↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ここ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
  const [name, setName] = useState("")
  const [email, setEmail] = useState("")
  const [password, setPassword] = useState("")
  //↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑

    const handleSubmit = async(e) => {
    //（バックエンドに投げてユーザー登録する処理）
      const response = await fetch("http://xxxx.com/user/reg",
        {
        method:"POST",
        body: JSON.stringify({
               name: name,
               email: email,
               password: password,
              }),
        })
    }

    return (
      <div>
        <form onSubmit={handleSubmit}>
          <input value={name} onChange={(e) => setName(e.target.value)} 
              type="text" name="name" required />
          <input value={email} onChange={(e) => setEmail(e.target.value)}
              type="text" name="email" required />
          <input value={password} onChange={(e) => setPassword(e.target.value)}
              type="text" name="password" required />
          <button>登録</button>
        </form>
      </div>
    )
  }
export default Register
```


ステート関数（`setName()`や`setEmail()`）は、HTMLの`<input>`タグに<strong>onChange={(e) =>setName(e.target.value)</strong>とインライン形式で指定され実行される。ありがちなパターン。



### ２．ステート変数を分割代入でまとめる書き方

次のように、各データ（ステート変数）をひとつのステート変数にまとめてしまう。ここでは`newUser`にまとめている。

```js
const Register = () => {
  const [newUser, setNewUser] = useState({
    name: "",
    email: "",
    password: "",
})

・・・省略・・・
```


こうした場合、まず関数を用意し（ここでは<strong>handleChange</strong>）、その中で次のようにステート変数のデータ書き込みを行う。

```js
const Register = () => {
  const [newUser, setNewUser] = useState({
    name: "",
    email: "",
    password: "",
})

    const handleChange = (e) => {
        //↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ここ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
        setNewUser({
            ...newUser,
            [e.target.name]: e.target.value,
        })
        //↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
    }

・・・省略・・・
```

ここで出てくるnewUserの前の点々`...`が<strong>分割代入</strong>（Destructuring assignment）と呼ばれるらしい。

HTMLの`<input>`タグのonChange=インラインはもちろん<strong>handleChange関数</strong>に変更する。

また、この中で例えばemailにアクセスしたい場合は`newUser.email`となる。したがって、`<input>`タグの**value値**も、例えばnameであったら`newUser.name`, emailであったら`newUser.email`と変更する。

```js
const Register = () => {
  const [newUser, setNewUser] = useState({
    name: "",
    email: "",
    password: "",
})

    const handleChange = (e) => {
        setNewUser({
            ...newUser,
            [e.target.name]: e.target.value,
        })

    const handleSubmit = async(e) => {
    //（バックエンドにフェッチする処理）
      const response = await fetch("http://xxxx.com/user/reg",
        {
        method:"POST",
        body: JSON.stringify({
               name: name,
               email: email,
               password: password,
              }),
        })
    }

    return (
      <div>
        <form onSubmit={handleSubmit}>
          <input value={newUser.name} onChange={handleChange} 
              type="text" name="name" required />
          <input value={newUser.email} onChange={handleChange}
              type="text" name="email" required />
          <input value={newUser.password} onChange={handleChange}
              type="text" name="password" required />
          <button>登録</button>
        </form>
      </div>
    )
  }
export default Register
```

こうすることで、複数の項目（nameやemail, password）を含んだ`newUser`が出来上がる。

さて、バックエンドに送るべきデータはすべてステート変数`newUser`に格納されているので、バックエンドにデータを投げる処理をする<strong>handleSubmit関数</strong>の中の、データ記述部分（`body`）も変更する。

これを:point_down_tone2:
```js
        body: JSON.stringify({
               name: name,
               email: email,
               password: password,
              }),
        })
```
このように変更:point_down_tone2:
```js
        body: JSON.stringify(newUser)
```

完成形

```js
const Register = () => {
  const [newUser, setNewUser] = useState({
    name: "",
    email: "",
    password: "",
})

    const handleChange = (e) => {
        setNewUser({
            ...newUser,
            [e.target.name]: e.target.value,
        })

    const handleSubmit = async(e) => {
    //（バックエンドにフェッチする処理）
      const response = await fetch("http://xxxx.com/user/reg",
        {
        method:"POST",
        body: JSON.stringify(newUser)
    }

    return (
      <div>
        <form onSubmit={handleSubmit}>
          <input value={newUser.name} onChange={handleChange} 
              type="text" name="name" required />
          <input value={newUser.email} onChange={handleChange}
              type="text" name="email" required />
          <input value={newUser.password} onChange={handleChange}
              type="text" name="password" required />
          <button>登録</button>
        </form>
      </div>
    )
  }
export default Register
```

### ３．あえてエラーを試してみる（この記事の肝）

```js
    setNewUser({
        ...newUser,
        [e.target.name]: e.target.value,
    })
```

なんとも不思議な書き方、こういうものだとスルーして良いのだが、いくつか意地悪を試してみる。

- 【疑問１】点々は３つでないとダメなのか？

【回答】
３つと決まっているようで、２つや４つにするとVS Codeが注意してくれる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307441/b4cc60cc-792b-f8cf-432f-dda8080515b3.png)

- 【疑問２】` [e.target.name]: e.target.value`と、**e.target.name**に`e.target.value`を割り当ててるコード部分がある。それを、`[e.target.email]: e.target.value`のように**email**や**password**にしてはダメなのか？

【回答】
ダメ。受け付けてくれない。ステート変数宣言部分をこのように:point_down_tone2:順番を入れ替えてもダメ。
```js
  //分割代入
  const [newUser, setNewUser] = useState({
    email: "",
    name: "", 
    password: "",
  })
```
<br/>

- 【疑問３】では、name, email共に二つ書いたり、name, email, password3つともすべて書くと:point_down_tone2:どうなのか？
```js
    setNewUser({
        ...newUser,
        [e.target.name]: e.target.value,
        [e.target.email]: e.target.value,
        [e.target.password]: e.target.value,
    })
```

【回答】
これではせっかくひとつ（`newUser`）にまとめた意味がないものの、受け付けてくれる。
<br/>

- 【疑問４】入力フォームに「名前」(name)欄が無い場合はどうなのか？ 当然ステート変数宣言は次のようなものになるが・・
```js
  const [newUser, setNewUser] = useState({
    email: "",
    password: "",
  })
```

【回答】
この場合はさすがに`[e.target.email]: e.target.value`であろうと推測した。しかしながら、実際はこの場合でも:point_down_tone2:のように`[e.target.name]: e.target.value`と**name**にしなければ受け付けてくれない。

```js
    setNewUser({
        ...newUser,
        [e.target.name]: e.target.value,
    })
```

### ４．残った疑問

結局、ここでの`[e.target.name]`は何を指しているのだろうか。
もしかしたらスキーマであろうか？ データベースに格納すべきデータのスキーマを次のように設定している（`UserSchema`）。しかし、これはバックエンドプログラムがMongoDBにデータを書き込むために用意された物。フロントでは使っていない。


```js
//utils/ShemaModels.js
const UserSchema = new Schema({
    name: {
        type: String,
        required: true
    },
    email: {
        type: String,
        required: true,
        unique: true
    },
    password: {
        type: String,
        required: true,
    }
})
```

やはり、不明のままである。:thinking:

<br />
<br />


## 本の宣伝
### Gatsbyバージョン４>>>>改訂新版


**前編**の『Gatsby4＋Tailwind＋Gatsby Cloudでつくる～』と**後編**の『JAMStackを学ぼうGatsby4＋microCMSでつくる～』を合わせ、次のようなデモサイトを構築します。
→ **https://yah-space.work**
<hr />


静的サイトジェネレーターGatsbyの基本とnode APIの扱いについて踏み込んだ解説書。またバージョン４の新機能《**DSG（静的サイトジェネレーション**》と《**Gatsby Functions**》での問い合わせフォーム実装、**Tailwind CSS**でのレイアウト、Gatsbyと相性が良い**Gatsby Cloud**を紹介し解説しております。


<a href="https://www.amazon.co.jp/JAMStack%E3%82%92%E5%AD%A6%E3%81%BC%E3%81%86%E5%88%9D%E7%B4%9A%E7%B7%A8Gatsby-React-bootstrap-Netlify%E3%81%A7%E3%81%A4%E3%81%8F%E3%82%8B%E4%BC%81%E6%A5%AD%E3%82%B5%E3%82%A4%E3%83%88%E7%AC%AC%EF%BC%92%E7%89%88-%E3%82%82%E3%81%86%E3%83%AC%E3%83%B3%E3%82%BF%E3%83%AB%E3%82%B5%E3%83%BC%E3%83%90%E3%83%BC%E3%81%AF%E3%81%84%E3%82%89%E3%81%AA%E3%81%84-ebook/dp/B08DKQ1Q9S?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&crid=1N4LBTLP3IIZA&keywords=Gatsby.js&qid=1659846164&s=digital-text&sprefix=gatsby.js%2Cdigital-text%2C206&sr=1-4&linkCode=li2&tag=kokkahasan-22&linkId=3bd81618c77ce73fb84ffc07fa5bfcab&language=ja_JP&ref_=as_li_ss_il" target="_blank"><img border="0" src="//ws-fe.amazon-adsystem.com/widgets/q?_encoding=UTF8&ASIN=B08DKQ1Q9S&Format=_SL160_&ID=AsinImage&MarketPlace=JP&ServiceVersion=20070822&WS=1&tag=kokkahasan-22&language=ja_JP" ></a><img src="https://ir-jp.amazon-adsystem.com/e/ir?t=kokkahasan-22&language=ja_JP&l=li2&o=9&a=B08DKQ1Q9S" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" />
<a target="_blank" href="https://www.amazon.co.jp/gp/product/B08DKQ1Q9S/ref=as_li_tl?ie=UTF8&camp=247&creative=1211&creativeASIN=B08DKQ1Q9S&linkCode=as2&tag=kokkahasan-22&linkId=4cd07e4678a3580955e9569f60d7ae6f">JAMStackを学ぼう Gatsby4＋Tailwind CSS＋Gatsby Cloudでつくるコーポレートサイト ～もうレンタルサーバーはいらない～ 改訂新版 前編（書籍2,980円）</a><img src="//ir-jp.amazon-adsystem.com/e/ir?t=kokkahasan-22&l=am2&o=9&a=B08DKQ1Q9S" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" />

<br />
<br />

GatsbyとmicroCMSを組み合わせてのコーポレートサイト作成手順を解説・ハンズオンした続編。待望の《**サイト内検索機能**》を《**Gatsby Functions**》と《**microCMSのqパラメータ**》で実装。
<a href="https://www.amazon.co.jp/JAMStack%E3%82%92%E5%AD%A6%E3%81%BC%E3%81%86%E4%B8%AD%E7%B4%9A%E7%B7%A8-Gatsby%E3%81%A8%E3%83%98%E3%83%83%E3%83%89%E3%83%AC%E3%82%B9CMS%E3%81%A7%E3%81%A4%E3%81%8F%E3%82%8B%E3%82%B3%E3%83%BC%E3%83%9D%E3%83%AC%E3%83%BC%E3%83%88%E3%82%B5%E3%82%A4%E3%83%88-%EF%BD%9EWordPress%E3%81%AF%E3%82%82%E3%81%86%E5%8F%A4%E3%81%84%EF%BD%9E-Atom-Yah-ebook/dp/B08KRPTW2R?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&crid=1N4LBTLP3IIZA&keywords=Gatsby.js&qid=1659846164&s=digital-text&sprefix=gatsby.js%2Cdigital-text%2C206&sr=1-3&linkCode=li2&tag=kokkahasan-22&linkId=27cc96bef513e3619bfbe81b68ec58a6&language=ja_JP&ref_=as_li_ss_il" target="_blank"><img border="0" src="//ws-fe.amazon-adsystem.com/widgets/q?_encoding=UTF8&ASIN=B08KRPTW2R&Format=_SL160_&ID=AsinImage&MarketPlace=JP&ServiceVersion=20070822&WS=1&tag=kokkahasan-22&language=ja_JP" ></a><img src="https://ir-jp.amazon-adsystem.com/e/ir?t=kokkahasan-22&language=ja_JP&l=li2&o=9&a=B08KRPTW2R" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" />
<a target="_blank" href="https://www.amazon.co.jp/gp/product/B08KRPTW2R/ref=as_li_tl?ie=UTF8&camp=247&creative=1211&creativeASIN=B08KRPTW2R&linkCode=as2&tag=kokkahasan-22&linkId=5ad235bbd59c9c43c5492687fb840791">JAMStackを学ぼう Gatsby4＋microCMSでつくるコーポレートサイト ～WordPressはもう古い～ 改訂新版 後編（書籍 2,580円）</a><img src="//ir-jp.amazon-adsystem.com/e/ir?t=kokkahasan-22&l=am2&o=9&a=B08KRPTW2R" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" />




<br /><br />