Reactを基本からまとめてみた【14】【React Hook (useContext) ① 】

##useContextとは

- useContextとは、Contextという機能をシンプルに扱えるようにする為のフック

#####⇨ 親からPropsで渡されていないのに、Contextに収容されているデータへよりシンプルにアクセスできる

##Contextとは

- 『状態』と『状態を変更するメソッド』とアプリ全体で共有する為の仕組み
- Contextを用いることで props のバケツリレーを回避できる

[Reactを基本からまとめてみた【12】【React Context】]
(https://qiita.com/kanfutrooper/items/6e0bfe20fdf76796caa1)

##Contextを扱う上で覚えておきたい用語
####Contextオブジェクト
- 親子関係になりComponent間で値を共有する為の道具
- 以下のProviderとConsumerという２つのComponentを持っている
- reactのcreateContext()を用いて作成する

####Context Provider
- Contextオブジェクトが持つComponentの１つ
- このComponentで囲まれた範囲に値を渡すことができる

```sample.js
function App() {
  return(
   <ContextObject.Provider value={100}>
    <ComponentA />
    <ComponentB />
   <ContextObject.Provider>
 );
}
```

####Context Consumer
- Contextオブジェクトが持つComponentの１つ
- Contextので共有したい値を受け取りたい箇所で使用する

```sample.js
function ComponentB() {
  return(
   <ContextObject.Consumer>
     {value => <div>値は{value}です</div>
   <ContextObject.Consumer>
 );
}
```

- useContext()を使うことでこのConsumerをシンプルに書くことができる

```sample.js
function ComponentB() {
  return(
    const value = useContext(ContextObject)
     {value => <div>値は{value}です</div>
}
```

##useContextの使い方

###ユーザのステータス（ログイン、ログアウト）によって画面に映る表示を変更するアプリを作成

####1. AuthProviderの作成

① src /context /AuthContext.tsx を作成する。 

```AuthContext.tsx
import React, { createContext } from 'react';

type Props = {
  children: React.ReactNode;
};

export const AuthContext = createContext<boolean>(false);

export const AuthProvider: React.VFC<Props> = ({children}) => {
  return (
     <AuthContext.Provider value={false}>{children}
     </AuthContext.Provider>
  )
};
```

####2.　App.tsxへAuthProviderを導入

```App.tsx
import React from 'react';
import { AuthProvider } from './context/AuthProvider';
import './App.css';

finction App() {
  return (
   <AuthProvider>
    <div className='App'>
     <h2>#4 useContext</h2>
　　　<UserAuth />
    </div>
   </AuthProvider>
  );
}
export default App;
```

####3.UIコンポーネントを作成

① src /components /userAuth/<br>UserAuth.tsx  <br>AuthButton.tsx <br>AuthDisplay.tsx を作成する。 

```AuthButton.tsx
import React from 'react';
import { AuthContext } from '../../context/AuthContext';

const AuthButton: React.VFC = () => {
  const auth = useContext(AuthContext);
  return (
    <React.Fragment>
      {auth ? <button>ログアウト</button> : <button>ログイン</button>}
    </React.Fragment>
 ); 
};
export default AuthButton;
```

```AuthDisplay.tsx
import React from 'react';
import { AuthContext } from '../../context/AuthContext';

const AuthDisplay: React.VFC = () => {
  const auth = useContext(AuthContext);
  return <div>{auth ? <p>ログイン</p>:<p>ログアウト</p>}</div>; 
};
export default AuthDisplay;
```

```UserAuth.tsx
import React from 'react';
import AuthButton from './AuthButton';

const UserAuth: React.VFC = () => {
  return (
   <div>
    <h4>ユーザ認証</h4>
    <AuthButton />
    <AuthDisplay />
   </div>
  ); 
};
export default UserAuth;
```
####4.useStateの導入

① AuthContext.tsxを修正する

```AuthContext.tsx
import React, { createContext, useState } from 'react';

type Props = {
  children: React.ReactNode;
};
type InitialState = {
  userAuth:boolean;
  setUserAuth:React.Dispatch<React.SetStateAction<boolean>>;
};

export const AuthContext = createContext<InitialState | null>(null);

export const AuthProvider: React.VFC<Props> = ({children}) => {
  const [useAuth, setUserAuth] = useState(false);
  return (
     <AuthContext.Provider value={{userAuth,setUserAuth}}>
       {children}
     </AuthContext.Provider>
  )
};
```

② AuthButton.tsxを修正する

```AuthButton.tsx
import React from 'react';
import { AuthContext } from '../../context/AuthContext';

const AuthButton: React.VFC = () => {
  const auth = useContext(AuthContext);
  console.log(auth);

  const handleSignOut = () => {
  auth?.setUserAuth(false);
};
   const handleSignIn = () => {
  auth?.setUserAuth(true);
};

  return (
    <React.Fragment>
      {auth?.userAuth ? (
       <button onClick={handleSignOut}>ログアウト</button> 
     ):( 
       <button onClick={handleSignIn}>ログイン</button>
     )}
    </React.Fragment>
 ); 
};
export default AuthButton;
```

③ AuthDisplay.tsxを編集する

```AuthDisplay.tsx
import React from 'react';
import { AuthContext } from '../../context/AuthContext';

const AuthDisplay: React.VFC = () => {
  const auth = useContext(AuthContext);
  return <div>{auth?.userAuth ? <p>ログイン</p>:<p>ログアウト</p>}</div>; 
};
export default AuthDisplay;
```
##参考サイト
[【ReactHooks入門】第4回：useContextの理解]
(https://www.youtube.com/watch?v=zEGvDDX-8i0&t=1s)
[React hooksを基礎から理解する (useContext編)]
(https://qiita.com/seira/items/fccdf4e73c59c491558d)