React.js&Next.js超入門 第2版の簡易メモのバグ修正

[React.js&Next.js超入門 第2版](https://www.shuwasystem.co.jp/book/9784798063980.html)で学習を進めていて、Chapter4の「簡易メモをつくる！」のサンプルコードでエラーが発生したので、解決方法を記しておきたいと思います。

:::note warn
私自身もReactをこちらの書籍で学習中の身ですがAmazonレビューでもサンプルコードが動かないことが指摘されており、困っている方もいるかと思うので記しておきます。
そのため、こちらの方法が最良の方法とは限らないことをご了承ください。
:::

# エラー発生箇所
エラーが発生している箇所は`Memo.js`の`setMode('deafult')`の箇所が原因で
`Error: Too many re-renders. React limits the number of renders to prevent an infinite loop.`エラーが発生します。

```Memo.js
import React, { useState, useEffect } from 'react'
import  usePersist  from '../Persist'

import Item from './Item'

function Memo(props) {
  const [memo, setMemo] = usePersist("memo", [])
  const [fmemo, setFMemo] = usePersist("findMemo", [])
  const [mode, setMode] = usePersist('mode', 'default')
  
  let data = []

  switch (mode){
    case 'default':
      data = memo.map((value,key)=>(
        <Item key={value.message} value={value} index={key + 1} />
      ))
      setMode('deafult') //←ここの処理が原因
      break
    
    case 'find':
      data = fmemo.map((value,key)=>(
        <Item key={value.message} value={value} index={key + 1}/>
      ))
      break

    default:
      data = memo.map((value,key)=>(
        <Item key={value.message} value={value} index={key + 1} />
      ))
  }
  
  return (
    <table className="table mt-4">
      <tbody>{data}</tbody>
    </table>
  )
}

export default Memo
```

# 解決方法
おそらく`setMode('deafult')`することで`case 'default'`内の処理が走り、また`setMode('deafult')`が走るというループが永遠に発生してしまうためにエラーが発生しまうのかと思います。
そのため、Memo.jsから`setMode('deafult')`を削除します。

```Memo.js
import React, { useState, useEffect } from 'react'
import  usePersist  from '../Persist'

import Item from './Item'

function Memo(props) {
  const [memo, setMemo] = usePersist("memo", [])
  const [fmemo, setFMemo] = usePersist("findMemo", [])
  const [mode, setMode] = usePersist('mode', 'default')
  
  let data = []

  switch (mode){
    case 'default':
      data = memo.map((value,key)=>(
        <Item key={value.message} value={value} index={key + 1} />
      ))
      // setMode('deafult') //←こちらを削除
      break
    
    case 'find':
      data = fmemo.map((value,key)=>(
        <Item key={value.message} value={value} index={key + 1}/>
      ))
      break

    default:
      data = memo.map((value,key)=>(
        <Item key={value.message} value={value} index={key + 1} />
      ))
  }
  
  return (
    <table className="table mt-4">
      <tbody>{data}</tbody>
    </table>
  )
}

export default Memo
```

しかし、`Memo.js`から`setMode('deafult')`を削除してしまうと、`mode`の値が`find`の場合にメモを追加しても追加した値を含むリストが表示されません。
そのため`AddForm.js`に`setMode('deafult')`を追加します。

```AddForm.js
import React, { useState, useEffect } from 'react'
import  usePersist  from '../Persist'

function AddForm (props) {
  const [memo, setMemo] = usePersist("memo", [])
  const [message, setMessage] = useState('')
  const [mode, setMode] = usePersist("mode", "default") //←こちらを追加

  const doChange = (e)=> {
    setMessage(e.target.value)
  }

  const doAction = (e)=> {
    const data = {
      message: message,
      created: new Date()
    }
    memo.unshift(data)
    setMemo(memo)
    setMode("default") //←こちらを追加
    setMessage('')
  }

  return (
    <form onSubmit={doAction} action="">
    <div className="form-group row">
      <input type="text" className="form-control-sm col" 
        onChange={doChange} value={message} required />
      <input type="submit" value="Add" 
        className="btn btn-primary btn-sm col-2" />
    </div>
    </form>
  )
}

export default AddForm

```

またこちらはおまけですが、`mode`の値が`find`の場合にメモを削除しても削除した値を除いたリストが表示されません。
そのため`DelForm.js`にも`setMode("default")`を追加してあげると良いと思います。

```DelForm.js
import React, { useState, useEffect, memo } from 'react'
import  usePersist  from '../Persist'

function DelForm (props) {
  const [memo, setMemo] = usePersist("memo", [])
  const [num, setNum] = useState(0)
  const [mode, setMode] = usePersist("mode", "default") //←こちらを追加

  const doChange = (e)=> {
    setNum(e.target.value)
  }

  const doAction = (e)=> {
    let res = memo.filter((item, key)=> {
      return key != num
    })
    setMemo(res)
    setMode("default") //←こちらを追加
    setNum(0)
  }

  let items = memo.map((value,key)=>(
    <option key={key} value={key}>
      {value.message.substring(0,10)}
    </option>      
  ))

  return (
    <form onSubmit={doAction}>
    <div className="form-group row">
    <select onChange={doChange} className="form-control-sm col"
      defaultValue="-1" >
      {items} 
    </select>
    <input type="submit" value="Del" 
      className="btn btn-primary btn-sm col-2" />
    </div>
    </form>
  )
}

export default DelForm
```

以上の修正で本来意図していたアプリの動作を再現することが出来ると思います。
少しでもこちらの書籍で学習されている方のお力になれれば幸いです。