【React】クリーンアップ関数がわかりづらかったので実践してみた。

React学習中に学んだクリーンアップ関数がよく分からなかったので、実際に動かして確認してみました。

# 【 目次 】
**◆ おさらい（必要な前提知識）**

**◆ 実行ソース**

**◆ 挙動確認**

# 【 おさらい  （必要な前提知識） 】
## ①useEffect
Reactの副作用フックの1つ。
propsやStateが更新されるなどで、画面の再描画が終わった後に処理を実行できるにするフック。

<br>
<br>

## ②マウント・アンマウント

https://ja.reactjs.org/docs/react-component.html

https://qiita.com/sazumy/items/abfecdf37fc3cef5c8e4


上記サイトより、

>コンポーネントのインスタンスが作成されてDOMに挿入されること。

コンポーネントが作成されて、
それがDOMに要素として追加されることを`マウント`というみたいです。

<br>

逆にDOMからコンポーネントが削除されることを`アンマウント`というとのこと。

<br>
<br>

## ③クリーンアップ関数
useEffectが実行される直前もしくは、コンポーネントが`アンマウント`される時に実行される関数。

https://takamints.hatenablog.jp/entry/cleanup-an-async-use-effect-hook-of-react-function-componet#:~:text=%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%A2%E3%83%83%E3%83%97%E9%96%A2%E6%95%B0%E3%81%AF%E5%89%AF%E4%BD%9C%E7%94%A8%E3%83%95%E3%83%83%E3%82%AF%E3%81%8C%E8%BF%94%E3%81%99%E9%96%A2%E6%95%B0%E3%81%A7%E3%81%99,%E3%81%9F%E6%99%82%E3%81%AB%E5%91%BC%E3%81%B3%E5%87%BA%E3%81%95%E3%82%8C%E3%81%BE%E3%81%99%E3%80%82&text=%E3%81%A8%E3%81%84%E3%81%86%E3%81%93%E3%81%A8%E3%81%AB%E3%81%AA%E3%82%8A%E3%81%BE%E3%81%99,%E3%81%95%E3%82%8C%E3%82%8B%E3%81%A8%E3%81%84%E3%81%86%E3%81%93%E3%81%A8%E3%81%A7%E3%81%99%E3%80%82

上記サイトより、
>クリーンアップ関数は副作用フックが返す関数です。この関数は
>
>" 副作用フックが呼び出されたあと、DOMがアンマウントされた時に"
>
>呼び出されます。

<br>
<br>

# 【 実行ソース 】
setInterval・ clearIntervalを利用し、1秒おきにタイマーをセット・更新する処理を行います。

**■Clock.tsx**

```react
import { useState, useEffect } from "react";

const UPDATE_CYCLE: number = 1000;

const KEY_LOCALE: "KEY_LOCALE" = "KEY_LOCALE";


export const Clock = () => {
  // State
  const [timestamps, setTimestamps] = useState(new Date());

  // locale
  const locale = "ja-JP";

  // 　呼び出し確認用カウンター
  let counter: number = 0;

  useEffect(() => {
    const timer = setInterval(() => {
      setTimestamps(new Date());
      counter++;
      console.log("セットインターバル作動中" + counter);
    }, UPDATE_CYCLE);

    // クリーンアップ関数
    return () => {
      clearInterval(timer);
    };
  }, []);


  return (
    <div>
      <p>
        <span id="current-time-label">現在時刻</span>
        <span>{timestamps.toLocaleString(locale)}</span>
      </p>
    </div>
  );
};

```

**■App.tsx**
```react
import { Clock } from "./components/Clock";

const App = () => {
  return (
    <>
      <Clock></Clock>
    </>
  );
};

export default App;
```

**■index.js**
```javascript
import ReactDom from "react-dom";
import App from "./App";

ReactDom.render(<App />, document.getElementById("root"));
```

<br>
<br>

# 【 挙動確認 】
今回はsandboxを利用して実行してみます。

https://codesandbox.io/s/new

<br>
<br>

## クリーンアップ関数あり

![スクリーンショット 2022-11-20 13.52.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/754263/60de633b-8733-4096-7d46-287889a4e120.png)

処理を実行すると、consoleが1秒ごとにcounter変数と一緒に増えていくのがわかります。

ここで、途中でマウントされているClockをコメントアウトしてみます。
すると、
![スクリーンショット 2022-11-20 13.55.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/754263/173e87b0-f998-f06c-d02c-fb3a805a79da.png)

console出力が止まりました。
つまり、コンポーネントがアンマウントされたことにより、
クリーンアップ関数が実行されたのでconsole出力が止まったようです。
```react
    // クリーンアップ関数
    return () => {
      clearInterval(timer);
    };
```

<br>
<br>

## クリーンアップ関数なし
次に、クリーンアップ関数をコメントアウトした状態で、処理を始めてみます。

![スクリーンショット 2022-11-20 14.01.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/754263/0dc7027b-c8af-accd-ac34-6b3552b787d3.png)

初期処理は同じです。
次にコンポーネントをコメントアウトしてみます。

![スクリーンショット 2022-11-20 14.02.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/754263/d10addc6-a055-384a-012f-f7a3f7ee65b8.png)

![スクリーンショット 2022-11-20 14.02.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/754263/afdb36cc-e908-0d17-8f07-8b155c6e3988.png)


setIntervalが止まらず動き続けているのが分かります。

このように、一度実行した処理が動き続けているとバグやメモリに多大な負荷を与えてしまうので、クリーンアップ関数が存在するようです。