Reactのコーディング時に使う基本的な技術

# useState

### 概要
変数の状態を変更すると、再描画する仕組みが可能

### サンプル

ボタンを押すたびにdataの値がインクリメントされ、描画されるサンプル

```js
import { useState } from "react";

export default function Home() {
    const [data, setData] = useState(0);
    return <button onClick={() => setData(data + 1)}>{data}</button>;
}
```

![useState.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139166/e3cf1744-a9fa-d757-be12-2583569638b8.gif)

<details><summary>解説</summary>

useStateは[変数, セッター関数]といった二つの戻り値を取る。
dataには初期値0が入り、dataの値変更と同時に再描画したい場合はsetData関数を使う。
setData関数に引数を渡してコールすると、Test()関数が再度呼ばれ、
その際dataにはsetData関数をコールした際の引数がセットされる。
</details>

# useRef

### 概要
DOMノードへの参照を保持することができ、
フォームで入力された値を取得する際などに活用できる。

### サンプル
ボタンを押すと、入力した文字がconsole出力されるサンプル。

```js
import { useRef } from "react";

export default function Home() {
    const inputText = useRef();
    const submit = (e) => {
        console.log(inputText.current.value);
    };
    return (
    <>
        <input ref={inputText} type="text" />
        <button onClick={() => submit()}>実行</button>
    </>    
    );
}
```

![useRef_.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139166/df398d6a-3fb6-364b-cfa4-cc5153027c6a.gif)


<details><summary>解説</summary>

useRefで生成したオブジェクトをJSXのref属性に渡すことで、参照をつけれる。
currentフィールドから現在の値を取ることができる。

※別案としてuseStateを使っても同じことができます。

```js
import { useState } from "react";

export default function Home() {
    const [inputText, setInputText] = useStatus();
    const submit = (e) => {
        console.log(inputText);
    };
    return (
    <>
        <input value={inputText} type="text" onChange={event => setInputText(event.target.value)} />
        <button onClick={() => submit()}>実行</button>
    </>
    );
}
```

</details>

# Context

### 概要
アプリケーション全体やコンポーネントを跨いで参照したいオブジェクトを格納、参照できる箱
createContextで作成し、useContextで参照する

### サンプル
dataという変数をContextに入れて、別のコンポーネント内で表示するサンプル。

```js
import { createContext, useContext } from "react";

export const DataContext = createContext();

export default function Home() {
  var data = "Data";
  return (
    <DataContext.Provider value={{ data }}>
        <Test />
    </DataContext.Provider>
  );
}

export function Test() {
  const { data } = useContext(DataContext);
  return <div>{data}</div>;
}
```

![スクリーンショット 2022-09-22 0.21.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139166/eb560a33-bcbb-5f49-5dfa-ec8772df74c7.png)

<details><summary>解説</summary>

createContextで作成したContextを使用したいコンポーネント(Text)を
Context.Providerで囲う。
使用する側ではuseContextにDataContextを渡すだけ(このためにexportを書いてある)

サンプルでは生成元と使用先が同じクラスに書いてあるが、実際には別ファイルになることが多いため、ContextをimportしてuseContextに渡してやる必要がある。
</details>


# useEffect

### 概要
コンポーネントの描画が終わった際に処理を実行できる。
例えば、描画後のテキストボックスにフォーカスを当てる処理などを入れられる。

::: note warn
※注意としてuseStateでの再描画時もuseEffectの処理が実行されます。
そのため、useEffect内でuseStateしていると無限描画編に入ります。
:::

### サンプル
描画後に入力ボックスにフォーカスをあてる

```js
import { useEffect, useRef } from "react";

export default function Home() {
  var inputRef = useRef();
  useEffect(() => {
    inputRef.current.focus();
  });

  return <input ref={inputRef} type="text" />;
}

```

![useRef.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139166/ecd6ac22-fc41-2e81-4f9c-d15b0ab5fa59.gif)

<details><summary>解説</summary>

useRefで入力ボックスの参照を保持する。
useEffect関数内で入力ボックスにフォーカスを当てる。
dataのuseStateの再描画が走ると、再度useEffectが走ってしまうので、第二引数にから配列を渡す。
(この配列は依存配列と呼ばれ、useEffectの実行条件に使われる。配列内に適当な変数を指定すると、描画した際にその変数が変更されている場合のみuseEffectを実行するようになる。
今回は空なので、初回以外は実行しないことになる。)
</details>

# 依存配列

### 概要
急に日本語出てきましたが、
依存配列はuseEffectなどで使える、実行する条件になる配列です。
useEffectの引数に配列を渡すと、前回の描画時と今回の描画で配列に変化があったときのみ実行されます。
空配列を渡すと初回描画のみ実行されます。

### サンプル
初回のみ入力ボックスにフォーカスをあてる。
ログありボタンでdataの値を変化させた時だけ、useEffectを呼び、変化しない場合は呼ばない。

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

export default function Home() {
  var inputRef = useRef();
  var [data, setData] = useState(0);
  useEffect(() => {
    inputRef.current.focus();
  }, []);

  useEffect(() => {
    console.log(data);
  }, [data]);

  return (
    <div>
      <input ref={inputRef} type="text" />
      <button onClick={() => setData(++data)}>ログあり</button>
      <button onClick={() => setData(data)}>ログなし</button>
    </div>
  );
}
```

![依存配列.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139166/a4a5c334-948c-626f-6de9-5648b66329a4.gif)


# useMemo

useMemoは使用頻度が少ないと思うのと、私のサンプルがよくないので最後にしました。
### 概要
依存配列がどうしても変化してしまうような場合、でもuseEffectは実行させたくない。
useMemoを使えばその時点の変数の状態をキープでき、useEffectなどと相性がいいです。

### サンプル
入力ボックスの内容が変化した時はconsoleに配列の内容を表示するが、
描画ボタンを押したときは表示しない。

サンプルの実用性がなさすぎて、いい例があったら差し替えたい。

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

export default function Home() {
  const [inputData, setInputData] = useState("aa,bb");

  return <div>
    <input value={inputData} onChange={event => setInputData(event.target.value)}></input>
    <Test text={ inputData }/>
  </div>;
}

export function Test({text}) {
  var ary = useMemo(() => text.split(","), [text]);
  var [, refresh] = useState();

  useEffect(() =>{
    console.log(ary);
  }, [ary]);
  
  console.log("描画");

  return <button onClick={() => refresh([])}>再描画</button>;
}
```

![useMemo.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139166/108c3c59-7762-f4d0-1be8-8dfa285f5e5e.gif)

<details><summary>解説</summary>

useMemoの部分に注目して、useMemo自体も依存配列が指定できるので、textの値が変化したときのみtext.splitが実行されます。変化がない場合は前回実行したtext.splitの結果をキャッシュしたものを返します。
これによって、textが変化しなかった場合は、aryも変化しないことになります。
ということでuseEffectが実行されない。
</details>