こんにちは、フロントエンドエンジニアの峯です。
今回は、React Hooks のuseContext
を使って、Webサービスには欠かせない認証処理を書いていきます。
大規模サービスであれば、Reduxを導入して認証情報をreducerで管理し、コンポーネントから参照する事ができると思います。
しかし、Reduxの導入コストは、それなりのサービス規模でなければ個人的に理にかなっていないなと感じるので、小さなサービスであれば導入はなるべく避けたいです。
そこで、React Hooksです!
hook機能は、Reactでは、バージョン16.8以降で導入可能な拡張機能です。
今回は、そのhook機能の中からuseContext
を使ってみます!
目次
やりたいこと
認証処理をuseContext
を使って、さまざまなコンポーネントから認証に関わる処理を叩けるような形を開発していきたいと思います。
(今回は最小限のロジックで紹介していきたいと思います。)
早速、最小限の環境を準備します!
ディレクトリ構造
/src
App.js
AuthMessage.js
index.js
ファイルの中身
index.js
import React from "react";
import ReactDOM from "react-dom";
import App from "./App";
ReactDOM.render(
<React.Fragment>
<App />
</React.Fragment>,
document.getElementById("root");
);
App.js
const App = () => {
return (
<div className="App">
<AuthMessage />
</div>
);
}
export default App
AuthMessage.js
const AuthMessage = ({ children }) => {
return (
<>
<h1>Hello CodeSandbox</h1>
<h2>{/* ここに認証結果とってくるようにしてみる */}</h2>
</>
);
};
export default AuthMessage;
useContext について
Reactはpropsによって、親から子へデータを渡すことができます。
しかし、親子関係が増え、ネスト構造が深くなると親から子へデータを渡す事が大変になります。
そこで便利なのがコンテクストです!コンテクスト機能を利用する事で手動で親から子へデータを渡す事なく、能動的にツリー構造の下位に対してどこへでもデータを渡す事ができます。
useContext
は、このコンテクスト構造を拡張するものです。
useContext
を利用することで、関数などを含めた構造化された情報をツリー構造の下位のコンポーネントから呼び出す事ができます。
Contextファイルの作成
では、認証周りのcontextファイルを作成していきます。
以下のファイルを新規作成します。
AuthContext.js
import React, { useContext } from "react";
const AuthContext = React.createContext();
export const useAuth = () => {
return useContext(AuthContext);
};
const AuthProvider = ({ children }) => {
const isAuth = () => {
/* 本来は、認証処理を書く */
return "認証済";
};
const value = {
isAuth
};
return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;
};
export default AuthProvider;
一つずつ解説していきます!
まず、コンテクスト機能のインスタンスを作成します。
作成したコンテクストに対して、hookのuseContext
に引数として渡します。
// インスタンスの作成
const AuthContext = React.createContext();
// hookにはコンテクストオブジェクトを渡す
export const useAuth = () => {
return useContext(AuthContext);
};
メインの関数です。
ここの関数は、useContext
によって、外部のコンポーネントから実行させる事ができます。
実行可能にするために、ここでは関数を一旦value
オブジェクトに格納して、<AuthContext.Provider>
コンポーネントのvalue
に渡すことで可能にします。
const AuthProvider = ({ children }) => {
// 認証処理を行う関数(今回は簡単にしてます)
const isAuth = () => {
return "認証済";
};
// 外部コンポーネントから叩く要素をまとめておく
const value = {
isAuth,
/*複数書ける!*/
};
// 呼び出す要素は value に渡す
return (
<AuthContext.Provider value={value}>
{children}
</AuthContext.Provider>
);
};
外部コンポーネントから読み込み
AuthContext
(コンテクストプロバイダー)コンポーネントでラップされたコンポーネントは、AuthContext
のvalueに渡された要素を呼び出す事ができるようになります。
ただ、コンテクストプロバイダーコンポーネントは、値が変化するたびに再レンダリングが走るので、利用には注意してください。
外部コンポーネントから呼び出します。
App.js
import AuthMessage from "./AuthMessage";
import AuthContext from "./AuthContext";
import "./styles.css";
const App = () => {
return (
<div className="App">
<AuthContext>
{/* 以下のコンポーネントは コンテクストの値を参照できます */}
<AuthMessage />
</AuthContext>
</div>
);
}
export default App
参照可能になったAuthMessage
コンポーネントで認証処理を実行します。
AuthMessage.js
import { useAuth } from "./AuthContext";
const AuthMessage = ({ children }) => {
/* フックの読み込み
* 実行可能なメソッドはvalueに渡された要素のみです */
const { isAuth } = useAuth();
return (
<>
<h1>Hello CodeSandbox</h1>
{/* AuthContext の isAuthが実行されます */}
<h2>{isAuth()}</h2>
</>
);
};
export default AuthMessage;
これで、認証処理をラップされたコンポーネントのどこからでも実行する事が可能になりました。
他にもユーザー情報を取得する関数などを追加したい場合は、対象の関数をvalueに渡すだけです。
さいごに
Reactのバージョンアップに応じてさまざまなhookが追加されています。
使ったことのないhookも増えてきたので、積極的に使っていかないといけないといけませんね。
最後までご覧いただきありがとうございました。