Reactを学ぶ中で必ず押さえておきたいこと②

## 0. はじめに

Reactについて、勉強したことを備忘録として限定記事でまとめていたのですが、暇だったので公開記事にしました。

※2018年に書いた記事：[**Reactを学ぶ中で必ず押さえておきたいこと①**](https://qiita.com/i-tanaka730/items/1ffb8c22fcddd11b56a4)

## 1. Reactとは
- UIコンポーネントを作成するためのライブラリことやな。
- Facebook社が開発しているから、期待値大やな。
- Reactを使うにあたり、**仮想DOM、JSX、コンポーネント**・・・といったワードが20000%の確率で出てくるんやな。

## 2. 仮想DOM

- そもそもDOMは、**Document Object Model**の略やな。
- つまりは、HTMLにアクセスする窓口のことやな。
- DOMを直接更新する場合、DOMが変更されるたびにブラウザがHTMLを解析してレンダリングするから、コストが高いんやな。
- 仮想DOMでは、ページ変更前と変更後の仮想DOMを比較して、差分箇所を見つけて、リアルDOMに反映してくれるんやな。だからパフォーマンスが出るみたいやな。

## 3. JSX
- JavaScriptの拡張言語で、HTMLライクな記述ができるようになるんやな。
- 以下のイメージやな。

```typescript:JSだと
return (
  React.createElement(
    'button',
    {className: 'info'},
    onClick: test
    'ぼたん');
);
```
```typescript:JSXだと
return (
  <button className="info" onClick={test}>ぼたん</button>
);
```
- 「JSだと」みたいに、`React.createElement`とか書いても、直感的じゃないから分かりにくいんやな。
- JSXは、結局はコンパイル時にReact要素(React.createElement)に変換される仕組みみたいやな。
- `{}`の中に変数を使えるんやな。
- タグを階層構成で書く感じやな。
- ただ、最上位のタグは1つにせんとあかんから、`<>`で囲めばいいんやな。<br>`<div>`で囲ってもいいけど、HTMLで見たときに余計な`<div>`タグが出てまうんやな。

```typescript:<>で囲むパターン
return (
  <>
    <button>ぼたん1</button>
    <button>ぼたん2</button>
  </>
);
```


## 4. コンポーネント
- UIの部品のことやな。
- コンポーネントっていうのは、見た目だけでなく、機能(○○を更新とか)も含んでのことを言うんやな。
- 部品化することで、再利用しやすくなるんやな。オブジェクト指向みたいなもんやな。
- 1コンポーネント1ファイルで書くのがいいみたいやな。
- **クラスコンポーネント**と**関数コンポーネント**に分類できるんやな。
- 以下のイメージやな。

```typescript:クラスコンポーネント
class Button extends React.Component {
    render() {
        return <button>...</button>
    }
}
```
```typescript:関数コンポーネント
const Button = (props) => {
    return <button>...</button>
}
```

- コンポーネントを組み合わせて画面を作っていくんやな。
- コンポーネントは親子関係にして作ってくんやな。親コンポーネント-子コンポーネントってことやな。
- 親コンポーネントから子コンポーネントにデータを受け渡すには、**Props**っていう仕組みを使うんやな。
- Propsを使うことで、子コンポーネントで表示する値を変更できる(＝固定にしなくていい)わけやな。
- Propsでは関数を渡したりもできるんやな。<br>例えば、ボタンクリックされたときに、子コンポーネントで値変更して、結果を親コンポーネントのstateを更新するときとかに使うんやな。

## 5. ライフサイクル

- ライフサイクルとは、コンポーネントが生成されてから破棄されるまでの期間のことやな。
- 以下のライフサイクルに分けられるみたいやな。シンプルやな。
    - **Mounting**・・・コンポーネントが生成される期間。
    - **Updating**・・・コンポーネントが変更される期間。
    - **Unmounting**・・・コンポーネントが破棄される期間。


## 6. React Hooks

- React 16.8(2020年2月)からReactに追加された機能やな。
- これを使う事で、関数コンポーネントでもstateを扱うことが出来る様になったんやな。
- React Hooksは、基本フックとして**useState・useEffect・useContext**があるみたいやな。<br>それ以外にも、**useReducer・useCallback・useMemo・useRef・useImperativeHandle・useLayoutEffect・useDebugValue**があるみたいやな。<br>とりあえず基本フックのみ記載するかな。

### 6-1. useState

- 状態の定義や更新ができるんやな。
- つまり、コンポーネント内の値を書き換えたいときに使えるんやな。
- ちなみに、stateが変更されされたり、propsが変更されたときに、コンポーネントが再描画されるんやな。
- useStateのsetを呼びだす際は、prevStateを使うことで、更新前の値を使用できるんやな。
- useStateの使用方法は以下のイメージやな。

```Compornent.tsx
import { useState } from 'react'

export const Compornent = () => {

  // state・・・現在の状態
  // setState・・・更新関数
  // 0・・・初期値
  const[count, setCount] = useState(0);

  const countUp = () => {

    // こっちやと「今画面に出てる値+1」をする
    // なので連打でボタン押下したとき等、カウントが合わなくなる可能性がある
    // setCount(count + 1);

    // こっちやと「変更前の値+1」してくれる
    // 連打でボタン押下したときも問題ない
    setCount(prev => prev + 1);
  }

  return (
    <>
      <input type="text" value={count}/>
      <button onClick={countUp}>+</button>
    </>
  )
}
```

### 6-2. useEffect

- useEffectは、レンダリングのタイミングで呼び出される処理のことやな。
- レンダリングに関係ない処理って意味で、副作用って呼ばれてるみたいやな。
- レンダリング後に、apiを呼び出したり、DB処理をしたい場合とかによく使われるみたいやな。
- useEffectが呼び出されるタイミングってのは、制御できるんやな。
- useEffectの使用方法は以下のイメージやな。

```Compornent.tsx
import { CompornentB } from './CompornentB'
import { useState, useEffect } from 'react'

export const CompornentA = () => {

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

  const countUp = () => {
    setCount(prev => prev + 1);
  }

  // 毎回のレンダリンで呼ばれる
  useEffect(() => {
    console.log("--- 毎回 ---")
    console.log(count)
  })

  // 初回のレンダリングのみ呼ばれる
  useEffect(() => {
    console.log("--- 初回 ---")
    console.log(count)
  }, [])

  // countが変更された場合のみ呼ばれる
  useEffect(() => {
    console.log("--- Count変更時 ---")
    console.log(count)
  }, [count])

  // レンダリングされる前に呼ばれる
  useEffect(() => {
    return () => {
      console.log("--- レンダリング前 ---")
      console.log(count)
   }
  })

  return (
    <>
      <input type="text" value={count}/>
      <button onClick={countUp}>+</button>
    </>
  )
}



```

### 6-3. useContex

- Storeが簡単に作れるようになる仕組みやな。
- コンポーネント間でデータの受け渡しができるようになるんやけど、Propsみたいに「親から子へ」っていう制約がなくなるんやな。
- つまり、Storeを使うことで、親から孫へデータを受け渡しできたりするんやな。というか、アプリケーション全体で使いまわせるんやな。
- useContexの使用方法は以下のイメージやな。

```_app.tsx
import '../styles/globals.css'
import type { AppProps } from 'next/app'

function MyApp({ Component, pageProps }: AppProps) {
  return (
    <>
      <label>--- appです ---</label>
      <br/>
      <Component {...pageProps} />
    </>
    ) 
}
export default MyApp
```

```index.tsx
import type { NextPage } from 'next'
import { CompornentA } from "./CompornentA"
import { TestContext } from "./store";

const Home: NextPage = () => {
  return (
    <TestContext.Provider value={{id : "123456"}}>
    <label>--- indexです ---</label>
    <br/>
    <CompornentA/>
    </TestContext.Provider>
  )
}

export default Home
```

```CompornentA.tsx
import { CompornentB } from './CompornentB'

export const CompornentA = () => {
  return (
    <>
      <label>--- CompornentAです ---</label>
      <br/>
      <CompornentB/>
    </>
  )
}
```

```CompornentB.tsx
import { useTestContext } from "./store";

export const CompornentB = () => {

  const {id} = useTestContext();

  return (
    <>
      <label>--- CompornentBです ---</label>
      <br/>
      <label>indexで設定した「{id}」を、CompornentBで表示しています</label>
    </>
  )
}
```

```store.tsx
import { useContext, createContext, useState } from "react"

type ContextType = {
  id: string
};

const testContext: ContextType = {
  id: ""
};

export const TestContext = createContext(testContext);

export function useTestContext() {
  return useContext(TestContext);
}
```