createContext

Chaerin Kim·2023년 12월 4일

createContext를 사용하면 컴포넌트가 제공하거나 읽을 수 있는 context를 생성할 수 있음.

const SomeContext = createContext(defaultValue)

Reference

createContext(defaultValue)

컴포넌트 외부에서 createContext를 호출하여 컨텍스트를 생성함.

import { createContext } from 'react';

const ThemeContext = createContext('light');

Parameters

  • defaultValue: Context를 읽는 컴포넌트 위의 트리에 일치하는 context provider가 없을 때 context에 적용할 값. 의미 있는 기본값이 없는 경우 null을 지정함. 기본값은 "최후의 수단"으로 사용되는 것. 기본값은 정적이며 시간이 지나도 변경되지 않음.

Returns

Context 객체를 반환함.

Context 객체 자체는 어떠한 정보도 보유하지 않고, 다른 컴포넌트가 읽거나 제공하는 context가 어떤 context인지를 나타냄. 일반적으로 상위 컴포넌트에서 SomeContext.Provider를 사용하여 context 값을 지정하고, 아래 컴포넌트에서 useContext(SomeContext)를 호출하여 값을 읽음. Context 객체에는 몇 가지 프로퍼티가 있음:

  • SomeContext.Provider는 컴포넌트에 context 값을 제공할 수 있음.
  • SomeContext.Consumer는 context 값을 읽는 대체 방법이며 거의 사용되지 않음.

SomeContext.Provider

컴포넌트를 context provider로 감싸면 내부의 모든 컴포넌트에 대해 이 context의 값을 지정할 수 있음:

function App() {
  const [theme, setTheme] = useState('light');
  // ...
  return (
    <ThemeContext.Provider value={theme}>
      <Page />
    </ThemeContext.Provider>
  );
}

Props

  • value: 이 provider 내에서 이 context를 읽는 모든 컴포넌트에 (깊이에 상관없이) 전달할 값. Context 값은 모든 타입이 될 수 있음. Provider 내부에서 useContext(SomeContext)를 호출하는 컴포넌트는 그 상위에 있는 가장 안쪽의 context provider의 value를 받음.

SomeContext.Consumer

useContext가 존재하기 전에, context를 읽던 방식:

function Button() {
  // 🟡 Legacy way (not recommended)
  return (
    <ThemeContext.Consumer>
      {theme => (
        <button className={theme} />
      )}
    </ThemeContext.Consumer>
  );
}

이 이전 방식은 여전히 작동하지만 새로 작성된 코드는 대신 useContext(SomeContext)를 사용하여 context를 읽어야함:

function Button() {
  // ✅ Recommended way
  const theme = useContext(ThemeContext);
  return <button className={theme} />;
}

Props

  • children: 함수. React는 useContext()와 동일한 알고리즘에 의해 결정된 현재 context 값으로 전달한 함수를 호출하고, 이 함수에서 반환한 결과를 렌더링함. 또한 React는 부모 컴포넌트의 context가 변경될 때마다 이 함수를 다시 실행하고 UI를 업데이트함.

Usage

Creating context

Context는 컴포넌트가 props를 명시적으로 전달하지 않고도 정보를 깊은 곳까지 전달할 수 있게 함.

우선, 컴포넌트 외부에서 createContext를 호출하여 하나 이상의 context를 생성:

import { createContext } from 'react';

const ThemeContext = createContext('light');
const AuthContext = createContext(null);

createContext는 context 객체를 반환함. 컴포넌트는 context를 useContext()에 전달하여 context를 읽을 수 있음:

function Button() {
  const theme = useContext(ThemeContext);
  // ...
}

function Profile() {
  const currentUser = useContext(AuthContext);
  // ...
}

기본적으로 받는 값은 context를 만들 때 지정한 기본값이 됨. 그러나 기본값은 절대 변경되지 않으므로 그 자체로는 유용하지 않음.

Context가 유용한 이유는 컴포넌트에서 다른 동적 값을 제공할 수 있기 때문:

function App() {
  const [theme, setTheme] = useState('dark');
  const [currentUser, setCurrentUser] = useState({ name: 'Taylor' });

  // ...

  return (
    <ThemeContext.Provider value={theme}>
      <AuthContext.Provider value={currentUser}>
        <Page />
      </AuthContext.Provider>
    </ThemeContext.Provider>
  );
}

이제 Page 컴포넌트와 그 안에 있는 모든 컴포넌트는 아무리 깊숙이 들어가도 전달된 context 값을 '보게' 됨. 전달된 context 값이 변경되면 React는 context를 읽는 컴포넌트도 다시 렌더링함.

참고: 컨텍스트 읽기 및 제공하기

Importing and exporting context from a file

서로 다른 파일에 있는 컴포넌트가 동일한 context에 접근해야 하는 경우가 종종 있음. 그렇기 때문에 context를 별도의 파일에 선언하는 것이 일반적임. 그런 다음 export을 사용하여 다른 파일에서 context를 사용할 수 있도록 할 수 있음:

// Contexts.js
import { createContext } from 'react';

export const ThemeContext = createContext('light');
export const AuthContext = createContext(null);

그런 다음, 다른 파일에서 선언된 컴포넌트는 import을 사용하여 이 context를 읽거나 제공할 수 있음:

// Button.js
import { ThemeContext } from './Contexts.js';

function Button() {
  const theme = useContext(ThemeContext);
  
  // ...
}
// App.js
import { ThemeContext, AuthContext } from './Contexts.js';

function App() {
  
  // ...
  
  return (
    <ThemeContext.Provider value={theme}>
      <AuthContext.Provider value={currentUser}>
        <Page />
      </AuthContext.Provider>
    </ThemeContext.Provider>
  );
}

이는 컴포넌트 가져오기 및 내보내기와 유사하게 작동함.


Troubleshooting

I can’t find a way to change the context value

다음과 같은 코드는 기본 context 값을 지정함:

const ThemeContext = createContext('light');

이 값은 절대 변하지 않음. React는 상위에서 일치하는 provider를 찾을 수 없는 경우에만 이 값을 fallback으로 사용함.

시간이 지남에 따라 context가 변경되도록 하려면 context provider더에 state와 래핑 컴포넌트를 추가할 것.

0개의 댓글