react hooks 学習記録

## 始めに
現在進行系でVueを学習中でありますが、reactとVueでは何が違うの？と考え勉強をはじめました。そこで、学習中のreact hooks勉強がてら復習していきます。

## react hooksとは
componentでのデータ管理や監視を行ってくれるreactが備えたAPI
では実際に学習していきます。

## useState
1, componentでもデータの状態管理を行う為に用いる
2, useStateを配列に分割代入し、data(変数),dataを更新する関数を設定する。
3, useState関数の引数はデフォルト値、空文字列や配列、オブジェクト、初期値は自由。実際に格納したいデータをイメージして設定する


実際にコードは下記のようになる。

```react

//まずはuseStateを使えるようにimport
import React, {useState} from 'react';

const App = () => {
  //useStateを定義..data名、メソッド名は任意の名称
  const [data, setData] = useState("");

  //stateの更新
  const changeData = (e) => {
     const changeData = e.target.value;
     setData(changeData);
  }
  return(
    <中略>
  );
}
```

## useEffect
1, componentでのデータ監視クを行う。
2, useEffect関数は第一引数にメソッドをとり、第二引数に配列をとる。
3, useEffectはjsxがrendingさた後に実行される。

```react

Vueで考えると
/ 第二引数：なし
// 第一引数：レンダリング時に毎回呼ばれる
useEffect(() => {});

// 第二引数：空配列
// 第一引数：初回のレンダリング時のみ呼ばれる
// → つまり mounted と同等
useEffect(() => {}, []);

// 第二引数：中身のある配列
// 第一引数：配列で渡した変数のいずれかに変更があった場合のみ呼ばれる
useEffect(() => {}, [aaa, bbb]);
```

userの認証情報を保持する際に活用できそうです。

```react

import React, {useState, useEffect} from 'react';

const App = () => {
  //useStateを定義..data名、メソッド名は任意の名称
  const [user, setUser] = useState({});

  //useEffectを定義しstateの監視を行う
　useEffect( () => {
    const getUser = async () => {
       const response = await axios.get('api/path');
       setUser(reaponse)
    }
  }, [user]);
  return(
    <中略>
  );
}
```

## useReducer
1, componentにおけるデータ管理手段。useStateよりビジネスロジックが複雑な場合活用
2, useReducerの引数は第１引数にreducer(関数)、第２引数にinitialState（初期値）を受ける。reducerは「現在のstate」とactionを受け取り、stateのの更新を行う。state = 状態　action = 状態に対して変化をもたらすトリガー

```react

import React, {useReducer} from 'react'
 
const initialState = 0
 
const reducer = (currentState, action) => {
    // actionには、操作内容が入る
    switch(action) {
        case 'increment': // increment -> action
            return currentState + 1
        case 'decrement': // decrement -> action
            return currentState - 1
        case 'reset': // reset -> action
            return initialState
        default:
            return currentState // どれにも当てはまらないとき
    }
}
 
const App = () => {
    const [count, dispatch] = useReducer(reducer, initialState)
 
    return (
        <div>
            <div>Count {count}</div>
            <button onClick={() => dispatch('increment')}>Increment</button>
            <button onClick={() => dispatch('decrement')}>Decrement</button>
            <button onClick={() => dispatch('reset')}>Reset</button>
        </div>
    )
}
```

## useContext
1, use constext とは 親から子コンポーネント間でのデータ受け渡しを階層に関係なくデータを渡せる機能。 

2, 基本的に親 → ひ孫にデータを渡す際は props を利用して親 → 子 → ひ孫といった流れでデータを渡していたが、useContext を利用することで親 → ひ孫と行った経路でデータを渡すことができる。


context 用の js ファイルを作成し管理、それを import する 下記の内容でひとまず OK

```react

//contexts/AppContext.jsx

import { createContext } from  'react';

const AppContext = createContext();

export default AppContext;
```

親コンポーネントで usaeContext 定義したファイルをを使用できるようにする。そしてそれをコンポーネントタグとして活用する。
これでラップされたどこの階層のcomponentでもデータを受け取ることができる。

```
import AppContext from './contexts/AppContext';

const App = () => {
  return() {
    <>
    //value属性として渡したいデータを登録。
      <AppContext　value={'this is useContex'}>
        登録してる子のコンポーネントとか
      </AppContext>
    </>
  }
}
```
データを受けたいコンポーネントで useContex を使用するように宣言する
useContext に渡す引数はコンテクストオブジェクト自体である。

```react

import React, {useContext} from 'react';

cosnt Children = () => {
  const value = useContex(AppContext);

  return (
    <>
    //これでデータを受け取る子とることができる
      <div>{value}</div>
    </>
  );
}
```

## useReducer, contextApi, useContextを用いたglobalState管理
コンポーネント単位でpropsを使用せずデータを管理しようとすると、reduxが必要であったが、useContext,useReducerを使用することができる。
あくまでコンポーネント単位でのデータ一元管理はuseContext,useReduxer用いるが、規模が大きなるに連れて、reduxが必要になってくる。

- data管理にはData Storeを作成する。
- Data Storeはinital State, Reducer, ContextAPIを用いる。
- inital State →　データの初期値。　
- ProviderでラップしてやることでGlobal Stateをどこの階層でも読み込むことができる。

```react
//Global stateの定義
//store/index.js

//initalState dataの初期化を行っている
const intialState = {
  popular: []
};

//reducerによるデータ管理
const reducer = (state, action) => {
  switch (action.type) {
    case "SET_POPULAR":
      return { popular: action.payload.popular };
    default:
      return state;
  }
};


//global state importすることで各componentで使用しることもできる
export const Store = createContext({
  globalState: intialState,
  setGlobalState: () => null
});

//componentとして登録する。Providerでラップしデータを渡す。
// childern nodeを受けているので、import先でStoreProviderでラップすることで親要素を全て取得している。
const StoreProvider = ({ children }) => {
  const [globalState, setGlobalState] = useReducer(reducer, intialState);
  return (
    <>
      <Store.Provider value={{ globalState, setGlobalState }}>
        {children}
      </Store.Provider>
    </>
  );
};
```

#### 登録先のコンポーネント
これでど階層でもuseContextを用いglobalState(state), setGlobalState(dispatch)を使用できるようになった


```react

import React from "react";
import ReactDOM from "react-dom";
import StoreProvider from "./store/index";

import App from "./App";

const rootElement = document.getElementById("root");
ReactDOM.render(
  <React.StrictMode>
    <StoreProvider>
      <App />
    </StoreProvider>
  </React.StrictMode>,
  rootElement
);

```

useContextでreducerを使用できるようにしてみる

```react
import React, { useContext, useState } from "react";
//storeをimport
import { Store } from "../store/index";


const Top = () => {
//Consumerを用いない代わりにuseContextを用いる
  const { globalState, setGlobalState } = useContext(Store);
    <>
      <Layout>
        <div>top page</div>
      </Layout>
    </>
  );
};
export default Top;
```

## 終わりに
react hooksについて振り返りをしました。他にもhooksがあるので随時、学習ように更新していきます。