React - Context API

da.circle·2023년 2월 6일
0

리액트에서 props를 부모-자식(위-아래)이 아닌 여러 컴포넌트에 전달해야 할 때 context를 사용하면 props로 넘겨주지 않아도 정보를 공유할 수 있다!
상황에 따라 Context를 사용하는 게 나은지, 컴포넌트로 넘겨주는게 나은지 판단을 잘 해야 효율적으로 사용할 수 있다(꼭 필요할 때만 사용하자!).

Redux vs Context API

Redux

  • 자바스크립트 라이브러리
  • 상태 컨테이너의 역할을 한다.
  • 리액트에서 전역 상태 관리 도구로 사용된다.
  • 모든 글로벌 상태를 하나의 상태 객체에 넣어서 사용한다.

Context API

  • Context 자체는 상태 관리 도구가 아니다.
  • 상태 관리는 useState, useReducer를 같이 사용해야 한다.
  • 보통 기능별로 Context를 만들어서 사용한다.

어떤 걸 사용해야 할까

  • 복잡한 상태 관리, 프로젝트의 규모가 클 때, 비동기 작업이 많다면 Redux
  • 리액트 트리 안에서 전역으로 값을 공유하고 싶을 때 Context API

사용방법

  • Context API는 Provider와 Consumer로 나뉜다.

Context 생성하기

JavaScript

  • createContext를 import 후에 React.createContext로 생성한다.
  • defaultValue는 적절한 Provider를 찾지 못했을 때만! 사용한다.
    만약 Provider를 통해 undefined로 보낸다 해도 값을 받은 컴포넌트들은 defaultValue를 읽지 않는다.
//context.js
import React, { createContext } from "react";

export const MyContext = React.createContext(defaultValue);

TypeScript

  • 자바스크립트와 같이 createContext로 생성하지만, type 또는 interface로 타입을 지정해야 한다.
  • 인터페이스에 정의한 값들의 초기값을 지정해주어야 한다.
////context.ts
import React, { createContext } from "react";

//type 예시
export type ContextType = "light" | "dark";

//interface 예시(배열, 함수)
interface ContextType {
  myArr: [],
  myFunc: (): void => {},
}

export const MyContext = createContext<ContextType>("light");
  • defaultvalue를 사용하지 않는 경우에는 타입에 null을 명시해야 한다.
import { createContext } from "react";

interface UserContextType {
  username: string;
}

const UserContext = createContext<UserContextType | null>(null);

Provider 생성하기

  • 데이터를 제공하는 부모 컴포넌트를 Provider안에 렌더링한다.
  • Provider 컴포넌트는 value Props를 받아서 하위 컴포넌트에 전달한다.
  • Provider하위에 또 다른 Provider를 배치할 수 있으며, 하위 Provider가 우선시된다.
  • Provider에서 초기값을 지정한 경우에는 createContext에 인자를 넣지 않아도 상관없다.
    createContext()

JavaScript

//App.js
import { useState } from "react";
import { MyContext } from './context';

const Add = () => {
  const [theme, setTheme] = useState("light");

  return(
    //MyContext에 해당하는 context를 provide
    <MyContext.Provider value={theme}>
      <MyComponent />
    </MyContext.Provider>
  );
}

TypeScript

//App.ts
import { useState } from "react";
import { ContextType,MyContext } from './context';

const Add = () => {
  const [theme, setTheme] = useState<ContextType>("light");

  return(
    <MyContext.Provider value={theme}>
      <MyComponent />
    </MyContext.Provider>
  );
}

Consumer 생성하기

  • context에서 데이터를 가져올 때 사용한다.

Context.Consumer

  • Context.Consumer의 자식은 함수여야 한다.
return(
  <MyContext.Consumer>
    {value => 로직~}
  </MyContext.Consumer>
)

useContext()

  • Context.Consumer보다 useContext()를 사용하면 더 쉽게 Context 데이터에 접근할 수 있다.
import { useContext } from "react";
import { MyContext } from "./context";

const MyTheme = () => {
  const theme = useContext(MyContext);
  
  return <p>현재 테마 : {theme}</p>
}

Context 흐름


상태 관리하기

  • useState, useReducer로 상태 관리가 가능하다.

useReducer

  • useState의 대체 함수이다.
  • 컴포넌트 상태 업데이트 로직을 컴포넌트에서 분리시킬 수 있다.
const [state, dispatch] = useReducer(reducer함수, 기본값);
  • (state, action) => newState의 형태로 reducer를 받는다.
  • state : 상태 값
  • dispatch : reducer와 짝을 이뤄 지정한 action을 발생시킨다.
    dispatch({type: 'action명'})
//카운터 만들기 예시

//초기값 설정
const initialState = {count: 0};

//reducer함수(반드시 이름이 reducer일 필요는 없다. 하지만 보통은 reducer라고 짓는 것 같다.)
function reducer(state, action) {
  switch (action.type) {
    //action.type이 increment라면 state.count에 1을 증가시킴
    case 'increment':
      return {count: state.count + 1};
    //action.type이 decrement state.count에 1을 감소시킴
    case 'decrement':
      return {count: state.count - 1};
    default:
      throw new Error();
  }
}

//useReducer 사용해서 상태값 관리
function Counter() {
  const [state, dispatch] = useReducer(reducer, initialState);
  return (
    <>
      Count: {state.count}
      <button onClick={() => dispatch({type: 'decrement'})}>-</button>
      <button onClick={() => dispatch({type: 'increment'})}>+</button>
    </>
  );

이론만 봐서는 어떻게 사용하는건지는 알겠는데.. 언제 어디서 써야 하는지 감이 오지 않는다.
간단한 예시를 통해서 연습을 먼저 해보고 필요하다면 프로젝트에 활용해봐야겠다.


출처
Context - React
Context | React TypeScript cheatsheet
Hooks API Reference(usecontext) - React
벨로퍼트와 함께하는 모던 리액트 - Context API를 사용한 전역 값 관리
Hooks API Reference - React
벨로퍼트와 함께하는 모던 리액트 - useReducer 를 사용하여 상태 업데이트 로직 분리하기

profile
프론트엔드 개발자를 꿈꾸는 사람( •̀ ω •́ )✧

0개의 댓글