[React] 🪁context API 사용법 (ft. useReducer)

TATA·2023년 2월 25일
0

React

목록 보기
14/32

▷ context API란?

리액트에 내장된 기능으로 props를 사용하지 않아도
특정 값이 필요한 컴포넌트끼리 쉽게 값을 공유할 수 있게 해준다.

Provider 하위에서 context를 공유하는 모든 컴포넌트는
Provider의 value props가 바뀔 때마다 다시 렌더링 된다.

주 목적: props-drilling을 피하는 것.

❗️참고) context는 아무것도 관리하지 않는다. 그저 값을 전달할 뿐이다.


🪁 createContext

import React, { createContext } from "react";

/* 변수에 저장해서 사용 */
export const MyContext = createContext(defaultValue);
/* defaultValue: Provider value값을 따로 지정하지 않았을 때 defaultValu의 값이 된다. */

🪁 Provider

Context 객체 안에는 Provider라는 컴포넌트가 들어있다.

공유하고자 하는 값을 value라는 Props로 설정하면
자식 컴포넌트에서 해당 값에 바로 접근을 할 수 있다.

<MyContext.Provider value={/* 어떤 값 */}>
  {props.children}
<MyContext.Provider>

🪁 useContext

useContext라는 Hook을 사용하여
Context에 넣은 값에 접근할 수 있다.

/* useContext 가져오기 */
import React, { useContext } from "react";
import { UserContext } from "../store/store.js"

export const Child = () => {
  const print = useContext(UserContext);
  console.log(print) // userStore의 user 정보가 출력됨

🪁 context API 예제

store / user.js

/* createContext 가져오기 */
import React, { createContext } from "react";

export const UserContext = createContext(); /* 변수에 저장해서 사용 */

const UserStore = (props) => {
  	const [age, setAge] = useState(7);
  
	const user = {
      name: "TATA",
      age,
      changeAge: (update) => setAge(update),
    };
  
  return (
    /* Provider의 value라는 Props를 설정하여 여러 컴포넌트에서 공유할 수 있다. */
  	<UserContext.Provider value={user}>{props.children}</UserContext.Provider>
  );
}
      

      
export default = UserStore;

App.js

import UserStore from "./store.js"
...

function App() {
  return (
  	<UserStore> /* 사용할 곳에 감싸주기 */
    	<Header />
    	<Child />
    	<Footer />
    </UserStore> /* 사용할 곳에 감싸주기 */
  )
}

Child.js

/* useContext 가져오기 */
import React, { useContext } from "react";
import { UserContext } from "../store/user.js"

export const Child = () => {
  const print = useContext(UserContext);
  console.log(print) // userStore의 user 정보가 출력됨
  
  return (
    ...
  )
}

▷ useReducer

useState의 대체 함수이다.
state가 많을 경우, state를 하나로 묶어주는 역할을 한다.

❗️참고) reducer는 순수함수이다.

⚙️ 기본 구조

const [state, dispatch] = useReducer(reducer, initialArg, init)

⚙️ context API + useReducer 예제

store / user.js

/* useReducer 가져오기 */
import React, { createContext, useReducer } from "react";

export const UserContext = createContext(); /* 변수에 저장해서 사용 */

const initialValue = {
  name: "TATA",
  age: 7,
}

const userReducer = (state, action) => {
  switch (action.type) {
    case "CHANGE_AGE":
      return { ...state, age: action.number };

    default:
      break;
  }
};

const UserStore = (props) => {
  const [state, dispatch] = useReducer(userReducer, initialValue);
  
  return (
    /* Provider의 value로 dispatch를 줌 */
  	<UserContext.Provider value={{ state, dispatch }}>{props.children}</UserContext.Provider>
  );
}
      

      
export default = UserStore;

App.js

import UserStore from "./store.js"
...

function App() {
  return (
  	<UserStore> /* 사용할 곳에 감싸주기 */
    	<Header />
    	<Child />
    	<Footer />
    </UserStore> /* 사용할 곳에 감싸주기 */
  )
}

Child.js

/* useContext 가져오기 */
import React, { useContext } from "react";
import { UserContext } from "./store/user";

export const Child = () => {
  const { dispatch, state } = useContext(UserContext);
  const { age } = state;

  const changeAgeFunc = () => {
    return dispatch({ type: "CHANGE_AGE", number: "29" });
  };

  const resetAgeFunc = () => {
    return dispatch({ type: "CHANGE_AGE", number: "7" });
  };

  return (
    <>
      <h2>Change TATA age</h2>
      <h3>{age}살 입니다.</h3>
      <button onClick={changeAgeFunc}>Real age</button>
      <button onClick={resetAgeFunc}>Character age</button>
    </>
  );
};

참고

⚙️ Action으로 분리하기

store / user.js

const initialValue = {
  name: "TATA",
  age: 7,
};

// 액션으로 분리
export const changeAgeAction = (number) => {
  return {
    type: "CHANGE_AGE",
    payload: {
      age: number,
    },
  };
};

const userReducer = (state, action) => {
  switch (action.type) {
    case "CHANGE_AGE":
      return { ...state, age: action.payload.age };

    default:
      break;
  }
};

Child.js

  const changeAgeFunc = () => {
    return dispatch(changeAgeAction(29));
  };

  const resetAgeFunc = () => {
    return dispatch(changeAgeAction(7));
  };


👉 (공식문서)Context
👉 (공식문서)useReducer
👉 context API 튜토리얼 블로그

profile
🐾

0개의 댓글