[React] useContext()


useContext()


React Hooks API
コンテキストオブジェクト(react.createContextから返された値)を受信し、そのコンテキストの現在の値を返します.contextの現在の値は、ツリーでこのHookを呼び出すコンポーネントに最も近いのvalue propで決定します.
デバイスに最も近いを更新すると、このHookはMyContext Providerに渡された最新のコンテキスト値を使用してレンダラーをトリガーします.親構成部品がReact.memoまたはshouldComponentUpdateを使用している場合でも、ユーザContextを使用している構成部品自体から再レンダリングされます.
userContextとして渡されるパラメータはcontextオブジェクト自体であることを忘れないでください.
  • 正しい使い方:ユーザーContext(MyContext)
  • 誤った使い方:ユーザーContext(MyContext.Consumer)
  • 誤用法:MyContext.Provider
  • userContextを呼び出した構成部品は、コンテキスト値を変更すると常に再レンダリングされます.構成部品の再レンダリングにかかるコストが高い場合は、注記このオプションを使用して最適化できるようになりました。

    Testing


    構成



    テストは簡単に2種類行いました.
  • Contextとは異なる2つのサブコンポーネント
    [StoreInput, Storeoutput, SecondStoreInput, SecondStoreOutput]
    (Contextごとにstateが1つある)
  • Contextは同じ2つのサブコンポーネントを有する
    [SecondStoreInput, SecondStoreInput2, SecondStoreOutput, SecondStoreOutput2]
    (1つのContextに2つのstateがある)
  • Code


    UseContextStore.js

    import React, {useState, createContext} from 'react';
    
    export const Store = createContext(null);
    
    export const SecondStore = createContext(null);
    
    export function UseContextStore({children}) {
    
        const [input, setInput] = useState('');
    
        const storeValue = {
            input, setInput
        }
    
        return (
            <Store.Provider value={storeValue}>
                {children}
            </Store.Provider>
        );
    }
    
    export function UseContextSecondStore({children}) {
    
        const [input1, setInput1] = useState('');
    
        // 하나의 Context에 두개의 값이 존재할 경우
        // const [input2, setInput2] = useState('');
    
        const storeValue = {
            input1, setInput1,
    
            // 하나의 Context에 두개의 값이 존재할 경우
            // input2, setInput2
        }
    
        return (
            <SecondStore.Provider value={storeValue}>
                {children}
            </SecondStore.Provider>
        );
    }

    UseContextApp.js

    import React from 'react';
    
    import {UseContextStore, UseContextSecondStore} from "./useContext_store/UseContextStore";
    
    import ChildInput from "./ChildInput";
    import ChildOutput from "./ChildOutput";
    
    
    function UseContextApp(props) {
        return (
            <UseContextStore>
                <UseContextSecondStore>
                    <div>
                        <ChildInput/>
                        <ChildOutput/>
                    </div>
                </UseContextSecondStore>
            </UseContextStore>
        );
    }
    
    export default UseContextApp;

    ChildInput.js

    import React from 'react';
    
    import StoreInput from "./StoreInput";
    import SecondStoreInput from "./SecondStoreInput";
    
    // 하나의 Context에 두개의 값이 존재할 경우
    // import SecondStoreInput2 from "./SecondStoreInput2";
    
    function ChildInput(props) {
        return (
            <div>
                {console.log('ChildInput render')}
                <p><b>StoreInput</b></p>
                <StoreInput/>
                <p><b>SecondStoreInput</b></p>
                <SecondStoreInput/>
    
                {/*하나의 Context에 두개의 값이 존재할 경우*/}
                {/*<p><b>SecondStoreInput2</b></p>*/}
                {/*<SecondStoreInput2/>*/}
            </div>
        );
    }
    
    export default ChildInput;

    StoreInput.js

    import React, {useContext} from 'react';
    
    import {Store} from "./useContext_store/UseContextStore";
    
    function StoreInput(props) {
    
        const { input, setInput } = useContext(Store);
    
        const InputOnChange = (event) => {
            setInput(event.target.value);
        }
    
        return (
            <div>
                {console.log('StoreInput render')}
                <input type="text" value={input} onChange={InputOnChange}/>
            </div>
        );
    }
    
    export default StoreInput;

    SecondStoreInput.js

    import React, {useContext} from 'react';
    
    import {SecondStore} from "./useContext_store/UseContextStore";
    
    function SecondStoreInput(props) {
    
        const { input1, setInput1 } = useContext(SecondStore);
    
        const InputOnChange = (event) => {
            setInput1(event.target.value);
        }
    
        return (
            <div>
                {console.log('SecondStoreInput render')}
                <input type="text" value={input1} onChange={InputOnChange}/>
            </div>
        );
    }
    
    export default SecondStoreInput;

    ChildOutput.js

    import React from 'react';
    
    import StoreOutput from "./StoreOutput";
    import SecondStoreOutput from "./SecondStoreOutput";
    
    // 하나의 Context에 두개의 값이 존재할 경우
    // import SecondStoreOutput2 from "./SecondStoreOutput2";
    
    function ChildOutput(props) {
        return (
            <div>
                {console.log('ChildOutput render')}
                <StoreOutput/>
                <SecondStoreOutput/>
    
                {/*하나의 Context에 두개의 값이 존재할 경우*/}
                {/*<SecondStoreOutput2/>*/}
            </div>
        );
    }
    
    export default ChildOutput;

    StoreOutput.js

    import React, { useContext } from 'react';
    
    import {Store} from "./useContext_store/UseContextStore";
    
    function StoreOutput(props) {
    
        const { input } = useContext(Store);
    
        return (
            <div>
                {console.log('StoreOutput render')}
                <p>{input}</p>
            </div>
        );
    }
    
    export default StoreOutput;

    SecondStoreOutput.js

    import React, { useContext } from 'react';
    
    import {SecondStore} from "./useContext_store/UseContextStore";
    
    function SecondStoreOutput(props) {
    
        const { input1 } = useContext(SecondStore);
    
        return (
            <div>
                {console.log('SecondStoreOutput render')}
                <p>{input1}</p>
            </div>
        );
    }
    
    export default SecondStoreOutput;

    SecondStoreInput2.js

    import React, {useContext} from 'react';
    
    import {SecondStore} from "./useContext_store/UseContextStore";
    
    function SecondStoreInput2(props) {
    
        const { input2, setInput2 } = useContext(SecondStore);
    
        const InputOnChange = (event) => {
            setInput2(event.target.value);
        }
    
        return (
            <div>
                {console.log('SecondStoreInput2 render')}
                <input type="text" value={input2} onChange={InputOnChange}/>
            </div>
        );
    }
    
    export default SecondStoreInput2;

    SecondStoreOutput2.js

    import React, { useContext } from 'react';
    
    import {SecondStore} from "./useContext_store/UseContextStore";
    
    function SecondStoreOutput2(props) {
    
        const { input2 } = useContext(SecondStore);
    
        return (
            <div>
                {console.log('SecondStoreOutput2 render')}
                <p>{input2}</p>
            </div>
        );
    }
    
    export default SecondStoreOutput2;

    テスト結果


    テスト画面



    各入力が
  • である場合、下部に入力値は
  • となる.
    2つの異なるContextのサブコンポーネント
    [StoreInput, Storeoutput, SecondStoreInput, SecondStoreOutput]
    (Contextごとに1つのstateがある)
  • StoreおよびSecondStoreは、各Contextが変更された場合にのみレンダリングされます.
    同じContextを持つ2つのサブコンポーネント
    [SecondStoreInput, SecondStoreInput2, SecondStoreOutput, SecondStoreOutput2]
    (1つのContextに2つのstateがある)
  • などのContextを使用すると、使用状態が変更されていなくても
  • のレンダリングが行われます.

    の最後の部分


    React HooksでサポートされているuseContext()を使用している場合は、propsを使用して値を渡す必要はありません.サブコンポーネントをレンダリングしても、そのコンポーネントを使用していない親コンポーネントはレンダリングされません.
    Reduxは、Reactの範囲全体にわたってコンポーネント間で値を伝達し、間欠的に使用する利便性を提供し、不要なレンダリングを回避します.ただし、1つのContextのみを使用すると、不要なレンダリングが発生する可能性があるため、データ間の関係を考慮してContextを実装する必要があります.
    ありがとうございます.