본문 바로가기

프로그래밍/React

리액트(React) - Context 알아보기

리액트를 공부하면서 쓰는 글이니 오류가 있을 수 있습니다. 있다면 알려주시면 감사하겠습니다!

 

이번에는 리액트 Context를 알아봅니다.

 

Context는 리액트 프로젝트에서 전역으로 사용되는 데이터를 이용할 때 사용되는 기능입니다. 애플리케이션 설정, 테마 같은 전역으로 공유되는 데이터를 이용할 때 유용합니다.

 

리액트를 하면서 데이터는 부모 컴포넌트에서 자식 컴포넌트로 데이터를 전달합니다. 하지만 Context를 사용하면 번거롭지 않게 부모에서 자식에게 데이터를 전달하지 않아도 됩니다.

 

Context를 사용하면 쉽게 데이터를 사용할 수 있지만 컴포넌트가 많고 복잡한 상황에서 Context를 사용하는 것이 좋습니다.

 

Context 생성하기

처음 Context 객체를 생성하려면 createContext() 메서드를 시용해 Context 객체를 만들 수 있습니다.

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

const ThemeContext = createContext({
    color: "skyblue"
});

export default ThemeContext;

createContext 메서드에 들어갈 인수는 생성한 Context에 기본 값입니다. 

 

Context 값 사용하기

Context의 값을 사용하려면 createContext로 생성한 객체에서 Consumer 컴포넌트를 사용해야 합니다.

 

Consumer 컴포넌트는 자식을 함수로 받아 렌더링 합니다. 이 함수는 Context의 값을 이용해 렌더링 되어야 하는 엘리먼트를 반환해야 합니다. 

//App.js
import React from "react";
import ThemeContext from "./ContextEx";

const App = () => {
    return (
        <div>
            <ThemeContext.Consumer>
                {value => (
                    <div>색상:{value.color}</div> //기본 값 skyblue
                )}
            </ThemeContext.Consumer>
        </div>
    )
}

export default App;

 

Consumer 컴포넌트의 Context 값은 Provider 컴포넌트가 가지고 있는 value 값과 같습니다. 만약 Provider 컴포넌트가 상위 컴포넌트에 없다면 값은 Context를 생성했을 때 지정한 기본 값이 사용됩니다.

 

Context 값 변경하기

Context 값을 변경하고 싶다면 Provider 컴포넌트를 사용해야 합니다. Provider 컴포넌트는 Context 값이 변경되면 Consumer 컴포넌트가 다시 렌더링 됩니다. Context 값의 변경은 Provider 컴포넌트의 value로 변경할 수 있습니다.

//App.js
import React from "react";
import ThemeContext from "./ContextEx";

const App = () => {
    return (
        <div>
            <ThemeContext.Provider value={{ color: "green" }}>
                <ThemeContext.Consumer>
                    {value => (
                        <div>색상:{value.color}</div> //green
                    )}
                </ThemeContext.Consumer>
            </ThemeContext.Provider>
        </div>
    )
}

export default App;

 

동적으로 Context 값 변경하기

클릭 같은 이벤트로 동적으로 값을 변경했을 때를 알아보겠습니다. Context를 생성할 때 컬러를 설정하는 빈 함수를 만들고 App 컴포넌트에서 useState를 이용해 state를 만들고 Provider 컴포넌트의 value에 state값과 변경 함수를 넣어주었습니다.

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

const ThemeContext = createContext({
    color: "skyblue",
    setColor: () => {}
});

export default ThemeContext;

//ColorBtn.js
import React from "react";
import ThemeContext from "./ContextEx";

const ColorBtn = () => {
    return (
        <ThemeContext.Consumer>
            {state => (
                <div>
                    <div>색상:{state.color}</div>
                    <button onClick={() => state.setColor("green")}>클릭 하여 변경</button>
                </div>
            )}
        </ThemeContext.Consumer>
    )
}

export default ColorBtn;

//App.js
import React, { useState } from "react";
import ColorBtn from "./ColorBtn";
import ThemeContext from "./ContextEx";

const App = () => {
    const [color, setColor] = useState("skyblue");

    return (
        <div>
            <ThemeContext.Provider value={{ color: color, setColor:setColor }}>
                <ColorBtn />
            </ThemeContext.Provider>
        </div>
    )
}

export default App;

Provider에서 넘겨준 seColor 함수가 호출되면 state값인 color가 변경되면서 Provider의 value가 변경되므로 다시 렌더링 됩니다.

 

좀 더 편하게 Context 사용하기

Context 에도 훅이 존재하며 클래스형 컴포넌트를 이용하고 있다면 contextType을 이용하면 좀 더 편하게 Context를 사용할 수 있습니다.

 

contextType

contextType은 클래스형 컴포넌트에서 Context를 좀 더 쉽게 사용할 수 있도록 합니다. 

 

contextType에 생성한 Context를 지정하면 클래스 내부에서 this.context를 이용해 Context 접근이 가능하며

static 변수로도 contextType을 사용할 수 있습니다.

//ColorBtn.js
import React, { Component } from "react";
import ThemeContext from "./ContextEx";

class ColorBtn extends Component {
    // static contextType = ThemeContext;
    
    render() {
        return (
            <div>
                <div>색상:{this.context.color}</div>
                <button onClick={() => this.context.setColor("green")}>
                    클릭 하여 변경
                </button>
            </div>
        );
    }
}

ColorBtn.contextType = ThemeContext;

export default ColorBtn;

하지만 contextType을 이용하면 여러 Context 사용이 불가능합니다. 따라서 여러 개를 이용해야 한다면 contextType을 사용하지 않거나 함수형 컴포넌트를 이용해 사용해야 합니다.

 

useContext() Hook

함수형 컴포넌트에서 useContext 훅을 사용하면 간단하게 Context를 사용할 수 있습니다. useContext의 값은 Hook을 호출하는 컴포넌트 중 가까이 있는 Provider의 value값입니다.

//ColorBtn.js
import React, { useContext } from "react";
import ThemeContext from "./ContextEx";

const ColorBtn = () => {
    const context = useContext(ThemeContext);
    return (
        <div>
            <div>색상:{context.color}</div>
            <button onClick={() => context.setColor("green")}>
                클릭 하여 변경
            </button>
        </div>
    );
};

export default ColorBtn;

 

참고

리액트를 다루는 기술(개정판) - 김민준 지음

https://ko.reactjs.org/docs/context.html

 

Context – React

A JavaScript library for building user interfaces

ko.reactjs.org