1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

React.contextとは?

Last updated at Posted at 2023-02-08

contextとは

コンポーネントツリーを越えてデータを共有する方法です。 子コンポーネントの深さが深まると、引き続けてState管理のためにpropsを渡さなければならない状況になってしまいます。 そのようなことを解決するためにcontext apiを提供します。 contextを利用すれば、コンポーネントツリー全体にデータを提供することができます。(props drillingを防ぐ) グローバルなデータを共有する必要があるときに使用!

contextの流れ

1. create Contextメソッドを使ってcontextを生成する。
2. 生成されたcontextを持ってcontext providerでコンポーネントツリーを包む。
3. value propを使ってcontext providerに希望する値を入力する。
4. context consumerにて必要なコンポーネントからその値を読み込む。

contextの例

ThemeContext.js
import React from 'react'

export const themes = {
    light: {
        foreground: '#000000',
        background: '#eeeeee',
    },
    dark: {
        foreground: '#ffffff',
        background: '#222222',
    },
}

export const ThemeContext = React.createContext(themes.dark);

React.createContext()を使って、共有したいデータを定義します。
これはthemes.darkをdefaultValueとして使うと言う定義になります。
defaultValueとはあるコンポーネントがProviderを探せない(親子関係❌)時に使う値です。

ThemedButton.jsx
import React, { Component } from 'react'
import { ThemeContext } from './ThemeContext';

class ThemedButton extends Component {
  render() {
      let props = this.props;
      let theme = this.context;
    return (
      <button 
        {...props} 
        onClick={props.changeTheme}
        style={{ backgroundColor: theme.background, color: theme.foreground }}>
            button1
      </button>
    );
  }
}
ThemedButton.contextType = ThemeContext;
export default ThemedButton;

React.createContext()で生成したContextオブジェクト(ThemeContext)を
希望するクラスのcontextTypeプロパティに指定できます。
このプロパティを活用して、クラス内でthis.contextを利用して該当Contextの最も近いProviderを探してその値を読むことができるようになります。

Example.jsx
import React, { Component } from 'react'
import { ThemeContext, themes } from './ThemeContext';
import ThemedButton from './ThemedButton';

export default class Example extends Component {
    constructor(props) {
        super(props);
        this.state = {
            theme: themes.light,
        };
        this.toggleTheme = () => {
            this.setState((prev) => ({
                theme: prev.theme === themes.dark ? themes.light : themes.dark,
            }));
         };
    }
  render() {
    return (
      <div>
          <ThemeContext.Provider value={this.state.theme}>
              <ThemedButton changeTheme={this.toggleTheme} />
              <ThemeContext.Consumer>
                  {(theme) => (
                        <div 
                            style={{
                                height: 300, 
                                    width:300, 
                                    backgroundColor: theme.background,}}
                                    ></div>
                                )}
              </ThemeContext.Consumer>
          </ThemeContext.Provider>
          <ThemedButton />
      </div>
    );
  }
}

<ThemeContext.Provider value={this.state.theme}>で囲まれている
<ThemedButton>のbackgroundColorはProvider value propsにより、backgroundColorは”light”になります。Providerはvalue propを受けてこの値を下位にあるコンポーネントに転送するためです。下位のThemedButtonをクリックすると、toggleThemeによって、backgroudColorが変わります。

<Context.Consumer>のthemeパラメータは、該当contextのProviderの中で上位ツリーから最も近いProviderのvaluepropと同じです。なので、<ThemedButton><Context.Consumer>のbackgroundColorは共有され、いつも同じです。
一番下の<ThemedButton /><ThemeContext.Provider>に囲まれていなため、
ThemeContext.jsの以下のロジックにより、いつもbackgroundColorはdarkです。
export const ThemeContext = React.createContext(themes.dark);

image.png

image.png

useContext Hook

useContextとは、contextオブジェクト(React.createContextで返還された値)を受け、そのcontextの現在の値を返還します。 class componentでは、this.contextの形でThemeContextの値を受けましたが、 function componentでは、useContextを使って、以下のように使うことが可能です。
ThemedButton.jsx
import React from 'react'
import { useContext } from 'react'
import { ThemeContext } from './ThemeContext'

export default function ThemedButton(props) {
    const theme = useContext(ThemeContext)
  return (
          <button 
        {...props} 
        onClick={props.changeTheme}
        style={{ backgroundColor: theme.background, color: theme.foreground }}>
            button1
            </button>
  )
}
1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?