【React初心者向け】useContext でコンテキストの値を変更する方法を徹底解説

2024-05-15

React useContext でコンテキストの値を変更する方法

React の useContext フックは、コンポーネント階層全体で状態やその他のデータを共有するための便利なツールです。コンテキストプロバイダーを使用して値をラップし、useContext フックを使用して子コンポーネントでアクセスできます。しかし、デフォルトでは、useContext で取得した値は変更できません。

このチュートリアルでは、useContext とカスタムフックを使用して、Reactコンポーネントでコンテキストの値を変更する方法について説明します。

要件

このチュートリアルを進める前に、以下の要件を満たしていることを確認してください。

  • React と React Hooks の基本的な知識
  • JavaScript の基本的な知識

手順

  1. コンテキストの作成

最初に、共有したいデータ用のコンテキストを作成する必要があります。これを行うには、createContext 関数を使用します。

import React from 'react';

const ThemeContext = React.createContext({
  theme: 'light',
});

export default ThemeContext;

このコードは、theme というプロパティを持つ ThemeContext というコンテキストを作成します。デフォルトのテーマは light に設定されています。

  1. コンテキストプロバイダーの作成

次に、コンテキスト値を提供するコンテキストプロバイダーを作成する必要があります。これを行うには、ThemeContext.Provider コンポーネントを使用します。

import React from 'react';
import ThemeContext from './ThemeContext';

const ThemeProvider = ({ children }) => {
  const [theme, setTheme] = useState('light');

  return (
    <ThemeContext.Provider value={{ theme, setTheme }}>
      {children}
    </ThemeContext.Provider>
  );
};

export default ThemeProvider;

このコードは、ThemeProvider というコンポーネントを作成します。このコンポーネントは、themesetTheme という 2 つのプロパティを持つ値オブジェクトを ThemeContext に提供します。theme プロパティは現在のテーマを表し、setTheme プロパティはテーマを変更するために使用されます。

子コンポーネントでコンテキスト値にアクセスするには、useContext フックを使用します。

import React from 'react';
import ThemeContext from './ThemeContext';

const MyComponent = () => {
  const { theme, setTheme } = useContext(ThemeContext);

  return (
    <div>
      <p>現在のテーマ: {theme}</p>
      <button onClick={() => setTheme('dark')}>ダークテーマに切り替え</button>
    </div>
  );
};

export default MyComponent;

このコードは、MyComponent というコンポーネントを作成します。このコンポーネントは useContext フックを使用して ThemeContext から themesetTheme プロパティを取得します。theme プロパティは現在のテーマを表示するために使用され、setTheme プロパティはテーマを dark に切り替えるために使用されます。

  1. カスタムフックの作成

コンテキストの値をより簡単に更新できるように、カスタムフックを作成できます。

import React, { useState } from 'react';
import ThemeContext from './ThemeContext';

const useTheme = () => {
  const { theme, setTheme } = useContext(ThemeContext);

  const toggleTheme = () => {
    setTheme(theme === 'light' ? 'dark' : 'light');
  };

  return { theme, toggleTheme };
};

export default useTheme;

このコードは、useTheme というカスタムフックを作成します。このフックは themetoggleTheme という 2 つのプロパティを返します。theme プロパティは現在のテーマを表し、toggleTheme プロパティはテーマを lightdark の間で切り替えるために使用されます。

子コンポーネントでカスタムフックを使用するには、次のようにインポートして呼び出すだけです。

import React from 'react';
import useTheme from './useTheme';

const MyComponent = () => {
  const { theme, toggleTheme } = useTheme();

  return (
    <div>
      <p>現在のテーマ: {theme}</p>
      <button onClick={toggleTheme}>テーマを切り替え</button>
    </div>
  );
};

export default MyComponent;

このコードは、MyComponent コン




React useContext でコンテキストの値を変更するサンプルコード

ファイル構成

この例では、以下の3つのファイルを作成します。

  • ThemeContext.js:コンテキストの作成
  • ThemeProvider.js:コンテキストプロバイダーの作成
  • MyComponent.js:コンテキスト値の取得と更新

ThemeContext.js

import React from 'react';

const ThemeContext = React.createContext({
  theme: 'light',
});

export default ThemeContext;

このファイルは、ThemeContext という名前のコンテキストを作成します。このコンテキストには、theme というプロパティがあり、デフォルト値は light に設定されています。

ThemeProvider.js

import React, { useState } from 'react';
import ThemeContext from './ThemeContext';

const ThemeProvider = ({ children }) => {
  const [theme, setTheme] = useState('light');

  return (
    <ThemeContext.Provider value={{ theme, setTheme }}>
      {children}
    </ThemeContext.Provider>
  );
};

export default ThemeProvider;

MyComponent.js

import React from 'react';
import ThemeContext from './ThemeContext';

const MyComponent = () => {
  const { theme, setTheme } = useContext(ThemeContext);

  return (
    <div>
      <p>現在のテーマ: {theme}</p>
      <button onClick={() => setTheme('dark')}>ダークテーマに切り替え</button>
    </div>
  );
};

export default MyComponent;

コードの実行

上記のコードを実行するには、以下の手順を実行します。

  1. 3つのファイルをプロジェクトディレクトリに作成します。
  2. index.js ファイルで、以下のコードを使用して ThemeProvider でラップされた MyComponent をレンダリングします。
import React from 'react';
import ThemeProvider from './ThemeProvider';
import MyComponent from './MyComponent';

const App = () => {
  return (
    <ThemeProvider>
      <MyComponent />
    </ThemeProvider>
  );
};

export default App;
  1. index.js ファイルを実行します。

このコードを実行すると、ブラウザに "現在のテーマ: light" というテキストが表示されます。"ダークテーマに切り替え" ボタンをクリックすると、テーマが "dark" に変更され、テキストが "現在のテーマ: dark" に更新されます。

この例は、React useContext でコンテキストの値を変更する方法を理解するための基本的なものです。より複雑なシナリオでは、カスタムフックや reducer を使用してコンテキストを管理する必要がある場合があります。

補足

  • この例では、useState フックを使用してコンテキストの値を管理しています。他のステート管理ライブラリを使用することもできます。
  • コンテキストの値を更新すると、コンテキストを消費するすべてのコンポーネントが再レンダリングされます。パフォーマンスが問題になる場合は、useMemo などのフックを使用して再レンダリングを最適化する必要があります。



React useContext でコンテキストの値を変更するその他の方法

Reducer を使用する

useReducer フックを使用して、コンテキストの値を更新するステート管理ロジックをカプセル化することができます。これにより、複雑なステート更新をより簡単に処理することができます。

import React, { useReducer } from 'react';

const ThemeContext = React.createContext();

const initialState = {
  theme: 'light',
};

const reducer = (state, action) => {
  switch (action.type) {
    case 'TOGGLE_THEME':
      return {
        ...state,
        theme: state.theme === 'light' ? 'dark' : 'light',
      };
    default:
      return state;
  }
};

const ThemeProvider = ({ children }) => {
  const [state, dispatch] = useReducer(reducer, initialState);

  return (
    <ThemeContext.Provider value={{ theme: state.theme, dispatch }}>
      {children}
    </ThemeContext.Provider>
  );
};

const MyComponent = () => {
  const { theme, dispatch } = useContext(ThemeContext);

  return (
    <div>
      <p>現在のテーマ: {theme}</p>
      <button onClick={() => dispatch({ type: 'TOGGLE_THEME' })}>
        テーマを切り替え
      </button>
    </div>
  );
};

export default ThemeProvider;

この例では、useReducer フックを使用して theme プロパティの更新を管理する reducer 関数を作成しています。ThemeProvider コンポーネントは、dispatch 関数を含む値オブジェクトを ThemeContext に提供します。MyComponent コンポーネントは dispatch 関数を使用してテーマを切り替えることができます。

カスタムコンテキストフックを使用する

useContext フックと useState フックを組み合わせて、コンテキストの値を更新するためのカスタムフックを作成することができます。これにより、コンテキストの値の更新ロジックを再利用しやすくなります。

import React, { useState } from 'react';
import ThemeContext from './ThemeContext';

const useTheme = () => {
  const { theme, setTheme } = useContext(ThemeContext);

  const toggleTheme = () => {
    setTheme(theme === 'light' ? 'dark' : 'light');
  };

  return { theme, toggleTheme };
};

const MyComponent = () => {
  const { theme, toggleTheme } = useTheme();

  return (
    <div>
      <p>現在のテーマ: {theme}</p>
      <button onClick={toggleTheme}>テーマを切り替え</button>
    </div>
  );
};

export default MyComponent;

この例では、useTheme というカスタムフックを作成して、theme プロパティの更新を管理しています。このフックは themetoggleTheme という 2 つのプロパティを返します。MyComponent コンポーネントは useTheme フックを使用してこれらのプロパティにアクセスし、テーマを切り替えることができます。

サードパーティライブラリを使用する

react-contextmobx などのサードパーティライブラリを使用して、コンテキストの値をより複雑な方法で管理することもできます。これらのライブラリは、状態管理、パフォーマンスの最適化、その他の高度な機能を提供します。

使用する方法は、具体的なニーズと要件によって異なります。

  • 単純な値更新の場合は、useState フックで十分です。
  • 複雑なステート更新の場合は、useReducer またはカスタムコンテキストフックを使用するとよいでしょう。
  • 高度な機能が必要な場合は、サードパーティライブラリを検討してください。

どの方法を選択する場合でも、コードが読みやすく、保守しやすいことを確認することが重要です。

React useContext でコンテキストの値を変更するには、さまざまな方法があります。適切な方法は、具体的なニーズと要件によって異なります。


javascript reactjs react-hooks


JavaScript の隠れた機能: String.indexOf で正規表現を使用する

String. prototype. match() メソッドを使用する:この例では、\b(javascript)\b という正規表現を使用しています。これは、javascript という単語が単語境界(\b)で囲まれている場合にマッチします。...


jQuery.fn 以外の方法:ネイティブ JavaScript とその他のライブラリ

例:上記の例では、$div は jQuery オブジェクトであり、length プロパティや hide() メソッドなど、jQuery. fn に定義されたプロパティやメソッドを利用することができます。jQuery. fn の役割:jQuery オブジェクトに共通する機能を提供する...


【保存版】JavaScriptで setInterval 関数の初回実行を遅延させない2つの主要なアプローチ

setTimeout 関数を併用する最初の呼び出しのみを setTimeout 関数で実行し、その後 setInterval 関数で定期実行に移行する方法です。この方法の利点は、シンプルで分かりやすいことです。一方、初回実行と定期実行で異なる処理を行う場合に煩雑になる可能性があります。...


【初心者向け】React/ReduxでTypeScriptエラー「Property "XXX" does not exist on type 'IntrinsicAttributes & IntrinsicClassAttributes'」が発生したときの対処法

このエラーは、TypeScriptとReact/Reduxの組み合わせで、コンポーネントに定義されていないプロパティを参照しようとしたときに発生します。具体的には、IntrinsicAttributes & IntrinsicClassAttributes 型に存在しないプロパティ XXX を参照しようとしています。...


ReactJS: "Maximum update depth exceeded" エラーの原因と解決策

"ReactJS: Maximum update depth exceeded" エラーは、React コンポーネントの更新処理が無限ループに陥り、スタックオーバーフローが発生したことを示します。これは、コンポーネントの状態更新が別の状態更新を呼び出すような状況で発生します。...