React

【React Hooks】useContextとは?概念や使い方を徹底解説!

こんにちは、アプリ開発者のテルです!

「useContextの使い方がわからない」とお悩みではないでしょうか?

テル

本記事ではそんな悩みを解決していきます!

本記事を読むメリット
  1. useContextの使い方をサンプルで理解できる
  2. コードを公開しているので、自分の環境で確かめることができる

【React Hooks】useContextとは

  1. グローバルに「データ」を管理することができるもの
  2. 「props」によるバケツリレーをしなくて済む

useContextを理解する上で、押さえておくべきポイントは上記の2点のみです。

では、詳しく解説していきます!

▶︎ 公式ドキュメントはこちら

useContextを使わなかった場合

今回は例として、最上位を「APPコンポーネント」とします。

useContextを使わなかった場合「APPコンポーネント」から「子コンポーネント」にpropsでバケツリレー形式でデータを送ることになります。

この形式だと、コンポーネントが増えれば増えるほど、どこを起点にデータの受け渡しが始まったのかが分かりずらくなってしまいます。

この問題を解決するのが「useContext」という訳です。

useContextを使った場合

最上位である「APPコンポーネント」に「useContext」でデータを定義します。

そうすることで「APPコンポーネント」を起点に、定義したデータをどこからでも扱うことができるようになるという訳です。

「useContext」を用いることで、グローバルにデータを管理することができます。

では、実際の使用例を見ていきましょう!

実際の使用例

プロジェクト構成

サンプルの「ディレクトリ構成」と「完成イメージ」は以下の通りです。

ディレクトリ構成

完成イメージ

上記は、追加機能のみを実装したTodoリストアプリです。フォームに値を入力し、ボタンを押すことで、Todoを追加することができます。

useContextを使うことで、stateや更新関数をグローバルに扱えるようにしています。

では、ソースコードを用いて解説していきます!

ソースコード

Index.js

import { StrictMode } from "react";
import { createRoot } from "react-dom/client";
import App from "./App";

const rootElement = document.getElementById("root");
const root = createRoot(rootElement);

root.render(
  <StrictMode>
      <App />
  </StrictMode>
);

App.js

import { Todo } from "./components/Todo";
import { TodoProvider } from "./context/TodoContext";

const App = () => {
  return (
    <>
      <h1>useContext</h1>
      {/**TodoProviderで囲んだ箇所でContextを使える */}
      <TodoProvider>
        <Todo />
      </TodoProvider>
    </>
  );
};

export default App;

context/TodoContext.jsx

import { createContext, useContext, useState } from "react";

// Contextの作成
const TodoContext = createContext();
const ContentContext = createContext();

const todoList = [
  {
    id: 1,
    content: "洗濯する"
  },
  {
    id: 2,
    content: "掃除機かける"
  },
  {
    id: 3,
    content: "ご飯作る"
  }
];

// グローバルに使いたいstateと更新関数を設定
// TodoProviderで囲んだ範囲で上記を使用できる
export const TodoProvider = ({ children }) => {
  const [todos, setTodos] = useState(todoList);
  const [content, setContent] = useState("");

  return (
    <TodoContext.Provider value={[todos, setTodos]}>
      <ContentContext.Provider value={[content, setContent]}>
        {children}
      </ContentContext.Provider>
    </TodoContext.Provider>
  );
};

// 作成したContextを外部から使いやすいようにする
export const useTodoContext = () => useContext(TodoContext);
export const useContentContext = () => useContext(ContentContext);

components/Todo.jsx

import { useContentContext, useTodoContext } from "../context/TodoContext";
import { v4 as uuidv4 } from "uuid";
import { List } from "./List";

export const Todo = () => {
  // 設定したものを取得する
  const [todos, setTodos] = useTodoContext();
  const [content, setContent] = useContentContext();

  const addTodo = () => {
    const newTodo = {
      id: uuidv4(),
      content: content
    };
    const newTodos = [...todos, newTodo];
    setTodos(newTodos);
    setContent("");
  };

  return (
    <>
      <input
        type="text"
        value={content}
        onChange={(e) => setContent(e.target.value)}
      />
      <button onClick={addTodo}>+</button>
      <List />
    </>
  );
};

components/List.jsx

import { useTodoContext } from "../context/TodoContext";

export const List = () => {
  // 設定したものを取得する
  const [todos] = useTodoContext();

  return (
    <>
      {todos.map((todo) => {
        return (
          <ul key={todo.id}>
            <li>{todo.content}</li>
          </ul>
        );
      })}
    </>
  );
};

簡単解説

ご覧の通り、useContextを使用することで、propsによるデータの受け渡しが行われていないことが分かります。

TodoContext.jsxで設定したContextは、グローバルに扱えるようになっているため、どのコンポーネントからでも使用することができます。

以上が、useContextの基本的な使い方です。

まとめ

今回は「useContextの使い方」を徹底解説しました。

React Hooksの機能の1つであるuseContextを使うことで、グローバルにデータを管理することができます。

良ければ上記のコードを参考に、色々と試してみてください。

最後までご覧いただきありがとうございました。ではまた!

エンジニア就活対策