Context API

Gunwoo Kim·2021년 9월 23일
0

React

목록 보기
17/21
post-thumbnail

Context API란?

Context API는 react에서 정식적으로 지원하고 있는 전역상태관리 API 입니다.
일반적인 React 애플리케이션에서 데이터는 위에서 아래로 (즉, 부모로부터 자식에게) props를 통해 전달되지만, 애플리케이션 안의 여러 컴포넌트들에 전해줘야 하는 props의 경우 (예를 들면 선호 로케일, UI 테마) 이 과정이 번거로울 수 있습니다. context를 이용하면, 트리 단계마다 명시적으로 props를 넘겨주지 않아도 많은 컴포넌트가 이러한 값을 공유하도록 할 수 있습니다.
리액트 Context 에서 확인 할 수 있습니다.

Context 구성요소

  • Context를 간단히 설명하자면 크게 Provider와 Consumer로 나뉩니다.
    • Provider는 전역 상태를 정의하고, 전역 상태를 update하는 로직이 있습니다.
    • Consumer로 전역 상태를 사용할 수 있습니다.
    • useContext 훅을 통해 상태를 관리할 수 있다.

참고
https://joecortopassi.com/articles/react-context-api

Context API 사용하기

우선 간단하게 todo 항목을 입력하는 부분과 렌더링 하는 부분을 추가하겠습니다.

context 생성하기

context에 todo 리스트를 추가하는 todos와 todos의 상태를 바꿔줄 함수인 setTodos를 추가하겠습니다.

//TodoContext.js
import { createContext, useState, useContext } from "react";

const TodoContext = createContext(); // 1

export const TodoProvider = ({ children }) => {
  const [todos, setTodos] = useState([]);

  return (
    <TodoContext.Provider value={{ todos, setTodos }}> // 2
      {children}
    </TodoContext.Provider>
  );
};

export const TodoConsumer = TodoContext.Consumer; // 3
export const useTodoContext = () => useContext(TodoContext); // 4
  1. createContext를 통해 Context를 사용할 항목을 정의한다.
  2. Provider에서 사용할 todos와, 목록을 업데이트 해주는 setTodos 함수를 넘겨준다.
  3. Consumer을 통해 상태를 관리해가 위해 추가해준다.
  4. Consumer와 동일한 상태를 관리하게 위한 훅을 설정해준다.
    3,4. 두가지 모두 2번에서 지정해준 Provider를 가져올수 있습니다.

Provier/Consumer

Provider는 context를 구독(Consumer)하는 컴포넌트들에게 context의 변화를 알린다.

  • Provider 하위(내부)에 있는 컴포넌트 중에 context를 구독(Consumer)하는 부분이 Provider의 value가 바뀔 때마다 다시 렌더링된다.
  • Provider 하위에 있다고 value가 업데이트 될 때마다 모든 컴포넌트가 다시 렌더링된다는 소리는 아니다. context를 구독이 포함되어 있는 컴포넌트도 다시 렌더링 되는 것은 아니다. 오로지 context.Consumer 부분만 rerender 된다.
  • 당연히, Provider 컴포넌트 외부에 있는 컴포넌트에는 변화를 감지하지 못한다.

Provider로 감싸기

Todo를 감지할 컴포넌트를 provider로 감싸야 한다. 모든 페이지에서 로그인 여부를 알아야 하므로 최상단에 넣었다.

// App.js
import { TodoProvider } from "./TodoContext";
import Todo from "./Todo";

function App() {
  return (
    <TodoProvider>
      <Todo />
    </TodoProvider>
  );
}

export default App;

Consumer, useContext로 변화 감지하기

  • TodoConsumer 내부에는 함수로 작성한다. 인자에 provider value에 할당했던 값이 전달 된다.
  • useContext를 통해 보다 쉽게 값을 사용할 수 있습니다.
import { useState } from "react";
import { TodoConsumer, useTodoContext } from "./TodoContext";

export default function Todo() {
  const [input, setInput] = useState("");
  const { todos, setTodos } = useTodoContext(); // 1

  const handleInput = (e) =>setInput(e.target.value);
  
  const handleSubmit = (e) => {
    e.preventDefault();
    setInput("");
    setTodos((prev) => [...prev, input]); // 2
  };

  return (
    <div>
      <form onSubmit={handleSubmit}>
        <input type="text" onChange={handleInput} />
      </form>

      <section>
        <article>
          useContext를 사용한 예제
          {todos.map((todo) => (
            <div>{todo}</div>
          ))}
        </article> // 2

        <TodoConsumer>
          {({ todos }) => (
            <article>
              Consumer를 사용한 예제
              {todos.map((todo) => (
                <div>{todo}</div>
              ))}
            </article>
          )}
        </TodoConsumer> // 3
      </section>
    </div>
  );
}
  1. TodoContext.js에서 선언한 useContext값을 구조 분해 할당으로 가져와서 사용할 수 있습니다.
  2. 가져온 context는 보기와 같이 기존의 state를 사용하듯이 사용할 수 있습니다.
  3. ConSumer의 경우 내부에 인자값으로 todos, setTodos를 사용할 수 있습니다.

context API를 간단하게 사용해봤습니다.
위 예제는 간단하게 구현한 것으로 useState를 통해 상태를 관리했지만 보다 복잡한 상태의 경우 useReduser을 통해 관리할 수 있습니다.

위에 사용된 코드를 확인해 볼 수 있습니다.
👉 https://github.com/kim-gunwoo/react-context-exam.git

0개의 댓글