Context

-  기존 컴포넌트의 props를 통한 데이터 전달방식 대신 컴포넌트 트리를 통해 곧바로 컴포넌트로 전달함

 

 

언제 Context를 사용해야 할까?

- 여러 개의 컴포넌트들이 접근해야 하는 데이터 : 로그인 여부, 로그인 정보, UI 테마, 현재 언어 등...

이 처럼 props를 통해 데이터 전달하는 방식은 실제 데이터를 필요한 컴포넌트가 깊어질 수록 복잡해진다.

 

 

Context를 사용한 방식

 

 

 

Context를 사용하기 전에 고려할 점

- 무조건 Context를 사용하는 것이 좋은게 아니다. 왜냐하면 컴포넌트와 Context가 연동되면 재사용성이 떨어진다.

- 다른 레벨의 많은 컴포넌트가 데이터를 필요로 하는 경우가 아니라면, 기존 사용방식인 props 를 사용하는게 좋다.

 

 

 

Context API

React.createContext() : context를 생성

const MyContext = React.createContext(기본값);

- 만약 상위 레벨에 매칭되는 Provider가 없다면 기본값이 사용 됨!

- 기본값으로 undefined를 넣으면 기본값이 사용되지 않음.

 

 

Context.Provider : 제공자라는 뜻, 데이터를 제공해주는 컴포넌트

<MyContext.Provider value={/* some value */}>

- value 는 Provider 하위에 있는 컴포넌트들에게 전달된다.

- Provider value에서 주의해야 할 사항

Provider 컴포넌트가 재렌더링될 때마다 모든 하위 consumer 컴포넌트가 재렌더링 됨.

 

 

이와 같이 state를 사용하여 불필요한 재렌더링을 막는다.

 

 

 

Class.contextType

- Provider 하위에 있는 클래스 컴포넌트에서 context 데이터에 접근하기 위해 사용함

- 지금은 사용하지 않기 때문에 이런게 있다라는 것만 알아주기

 

 

 

Context.Consumer

- context의 데이터를 구독

<MyContext.Consumer>
	{value => /* 컨텍스트의 값에 따라서 컴포넌트들을 렌더링 */}
</MyContext.Consumer>

 

 

function as a child

- 컴포넌트의 자식으로 함수를 사용하는 방법

// children이라는 prop을 직접 선언하는 방식
<Profile children={name => <p>이름: {name}</p>} />

// Profile 컴포넌트로 감싸서 children으로 만드는 방식
<Profile>{name => <p>이름: {name}</p>}</Profile>

 

 

Context.displayName

- Context 객체는 displayName이라는 문자열 속성을 가진다.

- 크롬의 React 개발자 도구에서는 Context의 Provider나 Consumer를 표시할 때 이 DisplayName을 함께 표시해준다.

const MyContext = React.createContext(/* some value */);
MyContext.displayName = 'MyDisplayName';

// 개발자 도구에 "MyDisplayName.Provider"로 표시됨
<MyContext.Provider>

// 개발자 도구에 "MyDisplayName.Consumer"로 표시됨
<MyContext.Consumer>

 

 

 

 

여러개의 Context 사용하기

다음과 같이 Provider를 중첩해서 사용 가능

 

 

 

useContext() Hook

- 함수 컴포넌트에서 Context를 보다 쉽게  사용할 수 있게 함

사용시 파라미터에 Context 객체를 넣어줘야 함

 

 

 

 

 

실습 : Context를 사용하여 테마 변경 기능 만들기

import React from "react";

const ThemeContext = React.createContext();
ThemeContext.displayName = "ThemeContext";

export default ThemeContext;

ThemeContext라는 Context를 만든다. 기본값은 없다.

 

 

 

import { useContext, userContext } from "react";
import ThemeContext from "./ThemeContext";

function MainContent(props) {
    const { theme, toggleTheme } = useContext(ThemeContext);

    return (
        <div
            style={{
                width: "100vw",
                height: "100vh",
                padding: "1.5rem",
                backgroundColor: theme == "light" ? "white" : "black",
                color: theme == "light" ? "black" : "white",
            }}
        >
            <p>안녕하세요, 테마 변경이 가능한 웹사이트 입니다.</p>
            <button onClick={toggleTheme}>테마 변경</button>
        </div>
    );
}

export default MainContent;

MainContent 컴포넌트는 ThemeContext로 부터 데이터를 가져와 해당 테마대로 렌더링을 하는 역할을 한다.

또한 테마 변경 버튼을 누를 경우 ThemeContext로 부터 받은 toggleTheme 함수를 호출하여 ThemeContext의 값을 변경하는 역할을 한다.

 

 

import { useState, useCallback } from "react";
import ThemeContext from "./ThemeContext";
import MainContent from "./MainContent";

function DarkOrLight(props) {
    const [theme, setTheme] = useState("light");

    const toggleTheme = useCallback(() => {
        if (theme == "light") {
            setTheme("dark");
        } else if (theme == "dark") {
            setTheme("light");
        }
    }, [theme]);

    return (
        <ThemeContext.Provider value={{ theme, toggleTheme }}>
            <MainContent />
        </ThemeContext.Provider>
    );
}

export default DarkOrLight;

DarkOrLight 컴포넌트에서 다음과 같이 작성한다.

Provider로 하위 컴포넌트에서 theme과 toggleTheme을 사용 가능하도록 만든다.

 

 

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';

import DarkOrLight from './chapter_14/DarkOrLight';

ReactDOM.render(
  <React.StrictMode>
  <DarkOrLight />
  </React.StrictMode>,
  document.getElementById('root')
);

// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();

 

실행 결과, 테마 변경 버튼을 누르면 테마가 변경되는 것을 확인할 수 있다.

'React' 카테고리의 다른 글

[React] react-router-dom v6  (0) 2024.08.30
[React] styled-component  (0) 2024.08.23
[React] Composition 방법과 Inheritance  (0) 2024.08.20
[React] 실습 : 섭씨온도, 화씨온도 표시하기  (0) 2024.08.19
[React] Lifting State Up  (0) 2024.08.19

+ Recent posts