React customHooks を利用してロジックとUIを切り離すまでをやってみた（4/5）〜不要なレンダリングが走らないための工夫（準備編）〜

## はじめに

React customHooks を利用してロジックとUIを切り離すまでをやってみたシリーズ

前回でUI部分となるコンポーネント作成はできたので

https://qiita.com/ryosuketter/items/1dee37be7e4fe62ef6f0

今回は、ロジックとUIは切り離せたましたが、不要なレンダリングが走らないための工夫を説明するための準備をしていきます。

具体的には、Reactの`memo`や`useCallback`を使った最適化をやっていきます。

## これまで

Hasuraにユーザーのデータと仮定してデータを作成し

https://qiita.com/ryosuketter/items/8b01d53d0609f78c2e0e

https://qiita.com/ryosuketter/items/59a05d4eb5c715287ded

データを外部APIとして取得できるようにして、Next.js（apollo）を使って、クエリやミューテーションできるようにしました

https://qiita.com/ryosuketter/items/9e18295d78dc12a1a7f5

Hasuraから取得したユーザーデータの一覧ページと詳細ページを作りながら、`SG`と`ISR`を学んできました

https://qiita.com/ryosuketter/items/442db08856093e6cfeea

## このシリーズの目次

- [このシリーズの方針](https://qiita.com/ryosuketter/items/1142c47913440369b660)
- customHooks を利用してロジックとUIを切り離すまで
    - [ロジックの作成](https://qiita.com/ryosuketter/items/67b168491fd5a186796e)
    - [コンポーネント（UI）作成](https://qiita.com/ryosuketter/items/1dee37be7e4fe62ef6f0)
    - [不要なレンダリングが走らないための工夫（準備編）](https://qiita.com/ryosuketter/items/548dbd70ae835fd66dfb)👈 今回はコレ
    - [不要なレンダリングが走らないための工夫（検証 & 改善編）](https://qiita.com/ryosuketter/items/4fb9b560b0d076491d91) 

## 最終的なゴール

以下のような構成のアプリを作ることです。

![スクリーンショット 2021-10-18 17.27.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14191/e8a9a2e1-2723-4fec-77ef-be3b9eefdd81.png)

### 目的（最終的なゴールを達成する）

- 仕事で使っている技術のキャッチアップと復習
- 使う可能性がある技術の理解度向上

## Childコンポーネントの作成

`useCallback`を使った最適化を説明したいだけの目的ですが、`Child.tsx`ファイルを作成します。

```
components/
└── Child.tsx
hooks/
pages/
```

### 中身

```tsx:components/Child.tsx
import { ChangeEvent, FormEvent, VFC } from 'react'

interface Props {
  printMsg: () => void // 引数がなくて返り値が何もないという意味
}

export const Child: VFC<Props> = ({ printMsg }) => {
  return (
    <>
      <p>Child Component</p>
      <button
        className="my-3 py-1 px-3 text-white bg-indigo-600 hover:bg-indigo-700 rounded-2xl focus:outline-none"
        onClick={printMsg}
      >
        click
      </button>
    </>
  )
}
```

次に、`components/CreateUser.tsx`に先ほど作成した`Child.tsx`をimportします。

<details><summary>長いので折りたたみます（`components/CreateUser.tsx`）</summary><div>

```tsx:components/CreateUser.tsx
import { VFC } from 'react'
import { useCreateForm } from '../hooks/useCreateForm'
import { Child } from './Child'

export const CreateUser: VFC = () => {
  const {
    handleSubmit,
    username,
    usernameChange,
    printMsg,
    text,
    handleTextChange,
  } = useCreateForm()
  return (
    <>
      <div className="mb-3 flex flex-col justify-center items-center">
        <label>Text</label>
        <input
          className="px-3 py-2 border border-gray-300"
          type="text"
          value={text}
          onChange={handleTextChange}
        />
      </div>
      <form
        className="flex flex-col justify-center items-center "
        onSubmit={handleSubmit}
      >
        <label>Username</label>
        <input
          className="mb-3 px-3 py-2 border border-gray-300"
          placeholder="New user ?"
          type="text"
          value={username}
          onChange={usernameChange}
        />
        <button
          className="my-3 py-1 px-3 text-white bg-indigo-600 hover:bg-indigo-700 rounded-2xl focus:outline-none"
          type="submit"
        >
          Submit
        </button>
      </form>
      <Child printMsg={printMsg} />
    </>
  )
}
```

</div></details>

`components/CreateUser.tsx`で、`components/Child.tsx`をimportして

`<Child />`に、関数`printMsg`と`handleSubmit`を渡しています。

## CreateUserをimportしたページを作成

まずは、以下のファイルを作成します。

```
components/
hooks/
pages/
└── hooks-memo.tsx
```

```tsx:pages/hooks-memo.tsx
import { VFC } from 'react'
import { Layout } from '../components/Layout'
import { CreateUser } from '../components/CreateUser'

const HooksMemo: VFC = () => {
  return (
    <Layout title="Hooks memo">
      <CreateUser />
    </Layout>
  )
}
export default HooksMemo
```

次回、検証するので、そのための準備をして終わります。

```
$ yarn build
$ yarn start
```

## まとめ

今回は、不要なレンダリングが走らないための工夫（Reactの`memo`や`useCallback`を使った最適化を説明したいがためのコンポーネントの配備）をしました。

## 次回

実際に検証をしつつ、Reactの`memo`や`useCallback`を使った最適化をしていきます。

## アウトプット100本ノック実施中

https://qiita.com/ryosuketter/items/713474dbd009870e4103