【React】初学者がuseStateとuseEffectをまとめてみました。


# はじめに

こんにちは！
ガク@Necono_Engineerと申します！
プログラミングスクールRUNTEQで現在Ruby on Railsを中心に学んでいます。今回はポートフォリオ作成のために`React`を学んでいる過程で出会った`useState`と`useEffect`についてまとめてみました!
![1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3364974/9496896c-379d-c545-3b12-6ff2a252473d.jpeg)


:::note warn
プログラミング初学者のため、内容に誤りがある可能性がございます。
もし間違いがあればご指摘いただけると幸いです。
:::
# React Hooks
今回学んだ`useState`と`useEffect`はReact Hooksの1つです。

## React Hooksとは?
2017年の9月にリリースされたReact16.8からの機能です。
以前は、クラスコンポーネントでしか扱えなかった、Stateやライフサイクルの機能を`Hooks`を使用することで**関数コンポーネント**に**取り付ける**(Hook up)ことができます。

# useState
特に頻繁に使用されるフックとして`useState`があります。
`useState`を使用することで関数コンポーネント内で`state(状態)`を保持することができるようになります。

### 使用方法
```
import { useState } from 'react';
```
トップレベルでuseStateをインポートすることで使用可能になります。
- 状態（`state`）とその状態を更新する関数（`setState`）を定義します。
- 初期値を設定します。
```
const [state, setState] = useState(false);
```
| 記述名                                                 | 備考                                   |
| ------------------------------------------------ | -------------------------------------- |
| [state](#state)                                  | 現在の値                               |
| [setState](#setState)                            | stateの状態を変更する関数              |
| [false](#false)                                  | 初期値|
                                                    
<br> 

## Stateとは？
Reactのコンポーネントは内部で「状態」を持つことができます。
### 状態
状態はアプリケーションやコンポーネントの現在の情報のことで、`state`と呼ばれます。

### **Stateの流れ**
1. コンポーネントの状態を保存
2. その状態が変更された時に自動的にコンポーネントを更新（再レンダリング）

例) **クリックすると数字が+1されるCounterコンポーネント**
```
import React, { useState } from 'react';

function Counter() {
  const [count, setCount] = useState(0);

  return (
    <div>
      <p>Current Count: {count}</p>
      <button onClick={() => setCount(count + 1)}>+1</button>
    </div>
  );
}

export default Counter;
```
[![Image from Gyazo](https://i.gyazo.com/3f0c84de427b8fabee60956d76167647.gif)](https://gyazo.com/3f0c84de427b8fabee60956d76167647)
↑ コンポーネントが内部で保持する`state`が更新されると、コンポーネントが再描画され画面上のUIが変化します。
上記のコードでは更新関数であるsetCountを呼び出すと状態が変化します。
```
<button onClick={() => setCount(count + 1)}>+1</button>
```
ボタンに onClick イベントハンドラーを追加し、クリックすると setCount 関数を呼び出して count の値を1増やすように設定しています。

更新関数(setのついたもの)は現在の count 値に 1 を加えた値で count を更新します。
```
setCount(count + 1)
```
そして、 
```
<p>Current Count: {count}</p>
```
この{count}の部分で現在のcountの値をJavaScript変数として表示しています。(JSX構文内ではJavaScriptの式を使用でき、{ }で表現されます。)

このように`useState`を使用することでコンポーネント内で動的な処理が可能になります!

# useEffect

`useEffect`は、React コンポーネント内で**副作用**を実行するために使用されるフックです。
### 副作用 
UIのレンダリングに直接関係しない操作を指します。
これには以下のようなものが含まれます
- API からデータを取得する
- タイマーをセットする
- DOM ノードを直接操作する など。

### 依存配列
useEffect には、第2引数として「依存配列」を渡すことができます。
```
useEffect(() => {
  // 副作用を実行する処理を記述する
}, [依存配列]);
```
| 記述名                                                 | 備考                                   |
| ------------------------------------------------ | -------------------------------------- |
| [副作用](#state)                                  | 第1引数                               |
| [依存配列](#setState)                            | 第2引数              |


- 依存配列が指定されている場合

配列内の値が変更されたときにのみ、副作用が再実行されます。
以下のコードでは(userId）が変化したときに、APIからユーザーのデータを取得するという副作用の処理を行います。
```
import React, { useState, useEffect } from 'react'; //useEffectの定義

function UserProfile({ userId }) {
  const [user, setUser] = useState(null);

  useEffect(() => {
    async function fetchUserData() {
      const response = await fetch(`https://api.example.com/users/${userId}`);
      const userData = await response.json();
      setUser(userData);
    }

    fetchUserData();
  }, [userId]);    // userIdが変更されたときのみこの副作用を実行

  return (
    <div>
      {/* ユーザーデータの表示 */}
      {user && <div>{user.name}</div>}
    </div>
  );
}

export default UserProfile
```
- 依存配列が空の場合（[]）

useEffectはコンポーネントがマウントされた後に一度だけ実行されます。
その後、propsやstateの変更があってUIが再描画された場合(再レンダリング)でも副作用は再実行されません。
### マウント
コンポーネントに対するDOMノードを作成、既存のDOMツリーに挿入し、webページ上にコンポーネントが初めて描画された時のことを言います。アンマウントはDOMノードが既存のDOMツリーから削除された時のことを言います。

以下のコードではコンポーネントがマウントされた時にタイマーをセットし、アンマウントされた時にクリアします。
```
import React, { useState, useEffect } from 'react';

function TimerComponent() {
  const [seconds, setSeconds] = useState(0);

  useEffect(() => {
    const intervalId = setInterval(() => {
      setSeconds(prevSeconds => prevSeconds + 1);
    }, 1000);

    return () => clearInterval(intervalId); // コンポーネントのアンマウント時にインターバルをクリア
  }, []); // 依存配列が空なので、マウント時にのみ実行される

  return <div>経過秒数: {seconds}</div>;
}
export default TimerComponent
```
[![Image from Gyazo](https://i.gyazo.com/37c07a0784131a1d22133fbf9540a6bf.gif)](https://gyazo.com/37c07a0784131a1d22133fbf9540a6bf)
- 依存配列が指定されていない場合：

副作用はコンポーネントの初回マウント時と、その後のすべての更新（再レンダリング）後に実行されます。stateやpropsのどの変更にも反応して副作用を実行します。
stateやpropsの更新 → UIの再描画 → 処理の実行の順番で行われ、コンポーネントが画面に表示されたときや更新されたときに特定のコードを実行することができます。

# まとめ
useStateとuseEffectを調べていくにつれてからReactの基礎概念である状態、副作用、マウントなどについても少しだけですが知ることができました。実践でフックを適切に扱えるよう今後も学習を進め、Reactへの理解をさらに深めたいと思います！

# 参考文献
書籍
- [基礎から学ぶReact Hooks](https://www.amazon.co.jp/s?k=%E5%9F%BA%E7%A4%8E%E3%81%8B%E3%82%89%E5%AD%A6%E3%81%B6+react%2Freact+hooks&adgrpid=127837717575&gclid=Cj0KCQiA4NWrBhD-ARIsAFCKwWsHr0okV6b_dUyIR20LeCR8fWO_Zj0O1VPiYx0QqNf7Aoe8BD9FQNEaAtUhEALw_wcB&hvadid=678960852714&hvdev=c&hvlocphy=1009526&hvnetw=g&hvqmt=e&hvrand=5451760031386615003&hvtargid=kwd-1432900552499&hydadcr=1824_13657019&jp-ad-ap=0&tag=googhydr-22&ref=pd_sl_2jsxjnclqu_e)
-  [Reactハンズオンラーニング 第2版 ―Webアプリケーション開発のベストプラクティス](https://www.amazon.co.jp/React%E3%83%8F%E3%83%B3%E3%82%BA%E3%82%AA%E3%83%B3%E3%83%A9%E3%83%BC%E3%83%8B%E3%83%B3%E3%82%B0-%E7%AC%AC2%E7%89%88-%E2%80%95Web%E3%82%A2%E3%83%97%E3%83%AA%E3%82%B1%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E9%96%8B%E7%99%BA%E3%81%AE%E3%83%99%E3%82%B9%E3%83%88%E3%83%97%E3%83%A9%E3%82%AF%E3%83%86%E3%82%A3%E3%82%B9-Alex-Banks/dp/4873119383/ref=sr_1_1?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&crid=PU617SO9YTUK&keywords=React%E3%83%8F%E3%83%B3%E3%82%BA%E3%82%AA%E3%83%B3%E3%83%A9%E3%83%BC%E3%83%8B%E3%83%B3%E3%82%B0&qid=1702217116&sprefix=%2Caps%2C188&sr=8-1)
- [TypeScriptとReact/Next.jsでつくる実践Webアプリケーション開発](https://www.amazon.co.jp/TypeScript%E3%81%A8React-Next-js%E3%81%A7%E3%81%A4%E3%81%8F%E3%82%8B%E5%AE%9F%E8%B7%B5Web%E3%82%A2%E3%83%97%E3%83%AA%E3%82%B1%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E9%96%8B%E7%99%BA-%E6%89%8B%E5%B3%B6-%E6%8B%93%E4%B9%9F-ebook/dp/B0B74C3TNQ/ref=sr_1_1?crid=1P08MXJ0P04EO&keywords=typescript%E3%81%A8react%2Fnext.js%E3%81%A7%E3%81%A4%E3%81%8F%E3%82%8B%E5%AE%9F%E8%B7%B5web%E3%82%A2%E3%83%97%E3%83%AA%E3%82%B1%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E9%96%8B%E7%99%BA&qid=1702217175&sprefix=TYpeScript%E3%81%A8%2Caps%2C190&sr=8-1)

記事

https://qiita.com/ayumu_jp/items/ed056817ea94e9423976

https://qiita.com/KokiSakano/items/c16a8daf03acdbd6c911