Chapter 15:Context API


Context APIとは?


これは、反応項目にグローバルに利用可能なデータがある場合に有用な機能です.

Context APIを使用したグローバル・ステータス管理フローについて


🤔 グローバルなデータの管理方法
伝統的に、
リアクターは素子間でデータを伝達し、(親→子)最上位素子にデータを格納する
◆下部にある構成部品(G)が状態値を変更する必要があり、他端にある構成部品(F)が状態値を更新する必要がある場合、変更後の値は上部から→Fに順序を変更して複雑な状況を生じる
メンテナンス性が悪い!
ContextAPIを使用すると、これらのデータ・ストリームを容易にすることができます.

Context APIの使い方に詳しい


コスメに詳しい

// color.js
import { createContext } from "react";

const ColorContext = createContext({ color: 'black' });

export default ColorContext;

//ColorBox.js
import React from 'react';
import ColorContext from '../contexts/color';

const ColorBox = () => {
    return (
        // 걍 쉽게 생각해서, 함수를 인자로 넣어준거임
        <ColorContext.Consumer>
            {value => (
                <div
                    style={{
                        width: '64px',
                        height: '64px',
                        background: value.color
                    }}
                />
            )}
        </ColorContext.Consumer>
    );
};

export default ColorBox;

// App.js
import React from 'react'
import ColorBox from './components/ColorBox'
function App() {
  return (
    <div>
      <ColorBox />
    </div>
  )
}

export default App
  • ColorContxet.パラメータとしてConsumerに関数を加え(値に基づいて長方形を表示)、Render Props(
  • )と呼ばれるConsumerに割り当てられた値colorにアクセスしてblackを割り当てる.
    const RenderPropsSample = ({ children }) => {
      return <div>결과: {children(5)}</div>;
    };
    
    export default RenderPropsSample;
    
     
    
    만약 위와 같은 컴포넌트가 있다면 추후 사용할 때 다음과 같이 사용할 수 있습니다.
    
    <RenderPropsSample>{value => 2 * value}</RenderPropsSample>;
     
    
    RenderPropsSample에게 children props로 파라미터에 2를 곱해서 반환하는 함수를 전달하면 해당 컴포넌트에서는 이 함수에 5를 인자로 넣어서 “결과: 10“을 렌더링합니다.

    Providerに詳しい


    Contextの値を変更できます
    import React from 'react'
    import ColorBox from './components/ColorBox'
    import ColorContext from './contexts/color'
    function App() {
      return (
        <ColorContext.Provider value={{ color: 'red' }}>
          <div>
            <ColorBox />
          </div>
        </ColorContext.Provider>
    
      )
    }
    
    export default App
  • Contextに割り当てられた値は
  • に変更されました.
    宣言
  • プロバイダ、値が割り当てられていない場合、エラー
  • 動的Contextの使用


    これまでは固定値しか使用できませんでした.
    では、Contextの値を更新する必要がある場合は、どうすればいいか見てみましょう.

    Contextファイルの変更

  • の値を入力必要はなく、
  • を入力することもできる.
    stateの値を変更した後
    // Color.js
    import React, { createContext, useState } from 'react';
    
    const ColorContext = createContext({
        state: { color: 'black', subcolor: 'red' },
        actions: {
            setColor: () => { },
            setSubcolor: () => { }
        }
    });
    
    const ColorProvider = ({ children }) => {
        const [color, setColor] = useState('black');
        const [subcolor, setSubcolor] = useState('red');
    
        const value = {
            state: { color, subcolor },
            actions: { setColor, setSubcolor }
        };
        return (
            <ColorContext.Provider value={value}>{children}</ColorContext.Provider>
        );
    };
    
    // const ColorConsumer = ColorContext.Consumer와 같은 의미
    const { Consumer: ColorConsumer } = ColorContext;
    
    // ColorProvider와 ColorConsumer 내보내기
    export { ColorProvider, ColorConsumer };
    
    export default ColorContext;
    
    //App.js
    import React from 'react';
    import ColorBox from './components/ColorBox';
    import { ColorProvider } from './contexts/color';
    const App = () => {
      return (
        <ColorProvider>
          <div>
            <ColorBox />
          </div>
        </ColorProvider>
      );
    };
    
    export default App;
    
    //ColorBox.js
    import React from 'react';
    import { ColorConsumer } from '../contexts/color';
    
    const ColorBox = () => {
        return (
            <ColorConsumer>
                {value => ( // value = {state} 로 설정하면, 비구조화 할당이된다.
                    <>
                        <div
                            style={{
                                width: '64px',
                                height: '64px',
                                background: value.state.color
                            }}
                        />
                        <div
                            style={{
                                width: '32px',
                                height: '32px',
                                background: value.state.subcolor
                            }}
                        />
                    </>
                )}
            </ColorConsumer>
        );
    };
    
    export default ColorBox;

    カラー選択構成部品の作成


    アクションで関数を呼び出す
    import React from 'react';
    import { ColorConsumer } from '../contexts/color';
    
    const colors = ['red', 'orange', 'yellow', 'green', 'blue', 'indigo', 'violet'];
    
    const SelectColors = () => {
        return (
            <div>
                <h2>색상을 선택하세요.</h2>
                <ColorConsumer>
                    {({ actions }) => (
                        <div style={{ display: 'flex' }}>
                            {colors.map(color => (
                                <div
                                    key={color}
                                    style={{ background: color, width: '24px', height: '24px', cursor: 'pointer' }}
                                    onClick={() => actions.setColor(color)}
                                    onContextMenu={e => {
                                        e.preventDefault(); // 마우스 오른쪽 버튼 클릭 시 메뉴가 뜨는 것을 무시함
                                        actions.setSubcolor(color);
                                    }}
                                />
                            ))}
                        </div>
                    )}
                </ColorConsumer>
                <hr />
            </div>
        );
    };
    
    export default SelectColors;
  • 現在、行動によって価値が変化する状態値
  • すなわち,ContextAPIを使用するためにはproviderとして包むことができ,その下部のコンポーネントはconsumerとしてvalueor actionを受け入れ,それを使用する.
    しかし、前にcontextファイルを変更しました.見開く

    ConsumerではなくHookまたはStaric ContextTypeを使用


    consumerの代わりに別の方法で値を取得

    「関数」useContextの使用

    import React, { useContext } from 'react';
    import ColorContext from '../contexts/color';
    
    const ColorBox = () => {
        const { state } = useContext(ColorContext);
        return (
            <>
                <div
                    style={{
                        width: '64px',
                        height: '64px',
                        background: state.color
                    }}
                />
                <div
                    style={{
                        width: '32px',
                        height: '32px',
                        background: state.subcolor
                    }}
                />
            </>
        );
    };
    
    export default ColorBox;
    
    useContextによるアクセス
    import React from 'react';
    import { ColorConsumer } from '../contexts/color';
    
    const ColorBox = () => {
        return (
            <ColorConsumer>
                {value => ( // value = {state} 로 설정하면, 비구조화 할당이된다.
                    <>
                        <div
                            style={{
                                width: '64px',
                                height: '64px',
                                background: value.state.color
                            }}
                        />
                        <div
                            style={{
                                width: '32px',
                                height: '32px',
                                background: value.state.subcolor
                            }}
                        />
                    </>
                )}
            </ColorConsumer>
        );
    };
    Consumer、Reder porpsモードでアクセス
    比較してみる
    関数型構成部品でuseContextを使用すると、ステータス値に直接アクセスできます.

    クラス静的ContextType

    import React, { Component } from 'react';
    import ColorContext from '../contexts/color';
    
    const colors = ['red', 'orange', 'yellow', 'green', 'blue', 'indigo', 'violet'];
    
    class SelectColors extends Component {
        static contextType = ColorContext;
    
        handleSetColor = color => {
            this.context.actions.setColor(color);
    //나중에 action에 접근할게 많아면
    //이렇게 간단화 시키자 const actions = this.context.actions //// actions.setColor(color);
        };
    
        handleSetSubcolor = subcolor => {
            this.context.actions.setSubcolor(subcolor);
        };
    
        render() {
            return (
                <div>
                    <h2>색상을 선택하세요.</h2>
                    <div style={{ display: 'flex' }}>
                        {colors.map(color => (
                            <div
                                key={color}
                                style={{
                                    background: color,
                                    width: '24px',
                                    height: '24px',
                                    cursor: 'pointer'
                                }}
                                onClick={() => this.handleSetColor(color)}
                                onContextMenu={e => {
                                    e.preventDefault();
                                    this.handleSetSubcolor(color);
                                }}
                            />
                        ))}
                    </div>
                    <hr />
                </div>
            );
        }
    }
    
    export default SelectColors;
    ContextType,contextType=Colorcontextに他の関数を静的にアクセスさせ,actionにアクセスすればよい.
  • ですが、ContextTypeではオブジェクトを静的に受信できないため、1つのコンテキストしか受信できないという欠点があります.