[React] Context API - props를 전역적으로 관리해보자

장성우·2022년 11월 21일
0
post-thumbnail

UseContext란?

useContext함수는 전역적으로 상태관리를 할 수 있는 도구이다. useContext는 전역적으로 상태를 관리하기에 props를 통해 많은 데이터를 전달하거나 잘못된 부분을 수정할 때 복잡한 과정을 줄여줄 수 있는 장점이 있다.

API 사용방법

1. React.createContext

createContext 함수 import 후 상태관리를 할 값(보통은 객체)을 넣어주면 컨텍스트 객체 생성이 완료된다. createContext에서 반환반은 값은 컴포넌트가 되거나, 컴포넌트를 포함하는 객체가 된다. 컴포넌트를 렌더링 할 때 리액트 트리 상위에서 가장 가까이 있는 Provider로부터 현재 값을 읽음

// src/store/theme-context.js
import { createContext } from 'react';

const ThemeContext = createContext(defaultValue)
// ThemeContext가 컴포넌트는 아니지만 컴포넌트를 포함할 객체이기에
// 파스칼 케이스로 명명함
export default ThemeContext;

defaultValue매개변수는 트리 안에서 적절한 Provider를 찾이 못했을 때만 쓰이는 값이다. (현실적으로는 컴포넌트를 독립적으로 테스트할 때 유용한 값임)

2. Context.Provider

특정 컴포넌트를 포함한 하위의 모든 컴포넌트의 상태값을 바꾸고 싶을 때는 특정 컴포넌트를 포함하고 있는 부모 컴포넌트의 <Context.Provider> 태그로 감싸주고 value 속성을 추가해 값을 바꾸어 주면 Provider 하위에 있는 컴포넌트 안에서 useContext가 반환하는 값이 Provider의 값과 같아진다.

import ThemeContext from './theme-context';

const ThemeContextProvider = (props) => {
    const themeContext = { border: '10px solid red' };
    return (
        <ThemeContext.Provider value={themeContext}>
            {props.children}
        </ThemeContext.Provider>
    );
};

export default ThemeContextProvider;

Context API 적용

// App.js
import { useContext } from 'react';
import { Helmet } from 'react-helmet';
import classes from './App.module.css';
import ThemeContext from './store/theme-context';
import ThemeContextProvider from './store/ThemeProvider';

const App = (props) => {
    return (
        <ThemeContextProvider>
            <div className={classes.root}>
                <Helmet htmlAttributes={{ lang: 'ko' }} />
                <h1>Hello World</h1>
                <Sub1 />
            </div>
        </ThemeContextProvider>
    );
};

function Sub1() {
    const theme = useContext(ThemeContext);

    return (
        <div style={theme}>
            <h1>Sub1</h1>
            <Sub2 />
        </div>
    );
}

function Sub2() {
    return (
        <div>
            <h1>Sub2</h1>
            <Sub3 />
        </div>
    );
}

function Sub3(props) {
    const themeCtx = useContext(ThemeContext);
    return (
        <div style={themeCtx}>
            <h1>Sub3</h1>
        </div>
    );
}

export default App;

3. Context.Consumer

<<MyContext.Consumer>
  {(ctx) => return (/* context 값을 이용한 렌더링 */)}
</MyContext.Consumer>

Context.Consumer의 자식은 함수여야 한다. 이 함수는 context의 현재값을 받고 리액트 노드를 반환한다. 이 함수가 받는 ctx 매개변수 값은 해당 context의 Provider 중 상위 트리에서 가장 가까운 Provider의 ctx props와 동일하다.

0개의 댓글