WEB/REACT

[React] ContextAPI๋ฅผ ์‚ฌ์šฉํ•ด์„œ TodoList๋งŒ๋“ค๊ธฐ(2) : contextAPI

mingzoo 2021. 2. 9. 13:45

contextAPI์— ๋Œ€ํ•ด์„œ๋Š” ์ฑ… ๐Ÿ“–๋ฆฌ์•กํŠธ๋ฅผ ๋‹ค๋ฃจ๋Š” ๊ธฐ์ˆ ๐Ÿ“–์—์„œ๋„ ๋‹ค๋ค˜์ง€๋งŒ ๊ฒ‰์œผ๋กœ๋Š” ์ดํ•ดํ–ˆ์ง€๋งŒ, ๋ชธ๊ณผ ๋งˆ์Œ ์ „์ฒด์ ์œผ๋กœ ์•„์ง ์ดํ•ด๋ฅผ ๋ชปํ•˜๊ณ  ๊นจ๋‹ซ์ง€ ๋ชปํ–ˆ๋‹ค๋Š” ์ƒ๊ฐ์ด ๋“ค์–ด์„œ contextAPI๋ฅผ ์‚ฌ์šฉํ•œ ์˜ˆ์ œ์ธ ํˆฌ๋‘๋ฆฌ์ŠคํŠธ๋ฅผ ์ฐพ์•„์„œ ๋‹ค์‹œํ•ด๋ณด๊ฒŒ ๋˜์—ˆ๋‹ค.

์ด๋ฒˆ ํฌ์ŠคํŠธ๋ฅผ ์“ฐ๋ฉด์„œ ์ •ํ•œ ๋‚ด ๋ชฉํ‘œ๋Š” ์ด ํฌ์ŠคํŠธ๋ฅผ ์“ฐ๋ฉด์„œ ๋‹ค ์“ฐ๊ณ  ๋‚˜์„œ๋Š” ๋‚ด๊ฐ€ contextAPI๊ฐ€ ๋ญ”์ง€ ์ œ๋Œ€๋กœ ์„ค๋ช…ํ•  ์ˆ˜ ์žˆ๊ณ  ์•Œ ์ˆ˜ ์žˆ๋„๋ก ๋งŒ๋“œ๋Š” ๊ฒƒ์ด๋‹ค.

์ด์ „ ํฌ์ŠคํŠธ๋Š” ์ด ํˆฌ๋‘๋ฆฌ์ŠคํŠธ๋ฅผ ๋งŒ๋“ค๋ฉด์„œ ์‚ฌ์šฉํ•œ styled-components์— ๋Œ€ํ•œ ์š”์†Œ๋“ค์„ ๊ณต๋ถ€ํ•ด๋ณธ ํฌ์ŠคํŠธ์ด๋‹ค.

minjoo-space.tistory.com/56

 

[React] ContextAPI๋ฅผ ์‚ฌ์šฉํ•ด์„œ TodoList๋งŒ๋“ค๊ธฐ(1) : styled-components

๋ฆฌ์•กํŠธ๋ฅผ ๋‹ค๋ฃจ๋Š” ๊ธฐ์ˆ ์—์„œ๋Š” ํˆฌ๋‘๋ฆฌ์ŠคํŠธ๋ฅผ ๋งŒ๋“œ๋Š” ์˜ˆ์ œ๋ฅผ ๋งŒ๋“ค์–ด๋ดค์—ˆ๋Š”๋ฐ, ๊ทธ ๋•Œ์™€ ๋‹ค๋ฅด๊ฒŒ ์ด๋ฒˆ์—๋Š” contextAPI๋ฅผ ์ด์šฉํ•ด์„œ ํˆฌ๋‘๋ฆฌ์ŠคํŠธ๋ฅผ ๋งŒ๋“ค์–ด๋ณด์•˜๋‹ค. ์•„์ง contextAPI์— ๋Œ€ํ•ด์„œ ๋ˆ„๊ตฌ์—๊ฒŒ ์„ค๋ช…ํ• 

minjoo-space.tistory.com

 

์ด ๊ธ€์€ ๊ณต์‹๋ฌธ์„œ์™€ ๋ฒจ๋กœํผํŠธ๋‹˜์˜ contextAPI๋ฅผ ์‚ฌ์šฉํ•œ ํˆฌ๋‘๋ฆฌ์ŠคํŠธ ๋งŒ๋“ค๊ธฐ๋ฅผ ์ฐธ๊ณ ํ•˜์—ฌ ์ž‘์„ฑํ•œ ๊ธ€์ž…๋‹ˆ๋‹ค.

 


Context

context๋ฅผ ์ด์šฉํ•˜๋ฉด ๋‹จ๊ณ„๋งˆ๋‹ค ์ผ์ผ์ด props๋ฅผ ๋„˜๊ฒจ์ฃผ์ง€ ์•Š๊ณ ๋„ ์ปดํฌ๋„ŒํŠธ ํŠธ๋ฆฌ ์ „์ฒด์— ๋ฐ์ดํ„ฐ๋ฅผ ์ œ๊ณตํ•ด์ค€๋‹ค.

์ผ๋ฐ˜์ ์œผ๋กœ๋Š” ๋ถ€๋ชจ๊ฐ€ ์ž์‹์—๊ฒŒ props๋ฅผ ์ „๋‹ฌํ•˜์ง€๋งŒ, ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์—ฌ๋Ÿฌ๊ฐœ๊ฐ€ ๋˜๊ณ  ๋ณต์žกํ•ด์ง€๋ฉด์„œ ์ด ๊ณผ์ •์ด ๋ฒˆ๊ฑฐ๋กœ์›Œ์ง‘๋‹ˆ๋‹ค. ์ด ๊ณผ์ •์—์„œ context๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋” ๊ฐ„๋‹จํ•˜๊ฒŒ ๊ตฌํ˜„ํ•ด์ค„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

์ด์ „ ์ƒํƒœ๊ด€๋ฆฌ

์ฒ˜์Œ์— ๋งŒ๋“ค์—ˆ๋˜ ์ฝ”๋“œ๋Š” App ์—์„œ todos ์ƒํƒœ์™€, onToggle, onRemove, onCreate ํ•จ์ˆ˜๋ฅผ ์ง€๋‹ˆ๊ณ  ์žˆ๊ฒŒ ํ•˜๊ณ , ํ•ด๋‹น ๊ฐ’๋“ค์„ props ๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์ž์‹ ์ปดํฌ๋„ŒํŠธ๋“ค์—๊ฒŒ ์ „๋‹ฌํ•ด์ฃผ๋Š” ๋ฐฉ์‹์œผ๋กœ ๊ตฌํ˜„ํ–ˆ๋‹ค.

์ง€๊ธˆ์€ ์ด๋ ‡๊ฒŒ ๊ตฌํ˜„ํ•ด๋„ ๋ฌธ์ œ๊ฐ€ ์—†์ง€๋งŒ, ํ”„๋กœ์ ํŠธ์˜ ๊ทœ๋ชจ๊ฐ€ ์ปค์ง€๊ณ  ๋ณต์žกํ•ด์ง„๋‹ค๋ฉด props๋ฅผ ์ „๋‹ฌํ•ด์ค˜์•ผํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋„ˆ์–ด์–ด์–ด๋ฌด ๊นŠ์ˆ™ํžˆ ์žˆ๊ฒŒ ๋  ์ˆ˜ ์žˆ๋‹ค.

๊ทธ๋ ‡๊ฒŒ ๋˜๋ฉด ๋„ˆ๋ฌด ๋ณต์žกํ•ด์ง€๊ธฐ ๋•Œ๋ฌธ์— context๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์•„๋ž˜ ์‚ฌ์ง„๊ณผ ๊ฐ™์ด ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค.

context API๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค๋ฉด!

Context๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์ „์—ญ ๋ฒ”์œ„๋กœ state๋ฅผ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ๊ฐ ์ปดํฌ๋„ŒํŠธ์—์„œ Direct Access ๊ฐ€๋Šฅ


๐Ÿค”์—ฌ๊ธฐ์„œ ์ž ๊น! dispatch๊ฐ€ ๋ญ์ง€?

๋ฆฌ๋•์Šค์— ๋Œ€ํ•œ ํฌ์ŠคํŠธ๋Š” ๋‚˜์ค‘์— ๋‹ค์‹œ ๋‹ค๋ค„๋ณผ ์˜ˆ์ •์ธ๋ฐ dispatch๊ฐ€ ๋ญ”์ง€ ์—ฌ๊ธฐ์„œ ๋จผ์ € ๊ฐ„๋‹จํžˆ ์งš๊ณ  ๋„˜์–ด๊ฐ€์•ผ๊ฒ ๋‹ค!

dispatch์— ๋Œ€ํ•ด์„œ๋Š” useReducer์—์„œ๋„ ์–ธ๊ธ‰์ด ๋์—ˆ์—ˆ๋‹ค. 

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

useReducer๋Š” useState์˜ ๋Œ€์ฒดํ•จ์ˆ˜๋กœ, (state, action)=>newState์˜ ํ˜•ํƒœ๋กœ reducer๋ฅผ ๋ฐ›๊ณ  dispatch ๋ฉ”์„œ๋“œ์™€ ์ง ํ˜•ํƒœ๋กœ ํ˜„์žฌ state๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

 

๋””์ŠคํŒจ์น˜๋Š” ์•ก์…˜์„ ๋ฐœ์ƒ์‹œํ‚ค๋Š” ์—ญํ• ์„ ํ•œ๋‹ค. 

์•ก์…˜์„ ๋ฐœ์ƒ์‹œ์ผœ์„œ ์Šคํ† ์–ด์—๊ฒŒ ์ƒํƒœ๋ณ€ํ™”๊ฐ€ ํ•„์š”ํ•˜๋‹ค๋Š” ๊ฒƒ์„ ์•Œ๋ ค์ค€๋‹ค!

๊ทธ๋ ‡๊ฒŒ ํ˜ธ์ถœ๋œ ์•ก์…˜์€ useReducerํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœ์‹œํ‚ค๊ณ  ์ƒํƒœ๋ฅผ ๋ณ€ํ™”์‹œํ‚ค๋Š” ๊ณผ์ •์„ ๊ฑฐ์น˜๊ฒŒ ๋œ๋‹ค.

์ƒํƒœ๊ด€๋ฆฌ๋ฅผ ์œ„ํ•œ ๊ฒƒ์ด๋ผ๊ณ  ๊ฐ„๋‹จํžˆ ์ดํ•ดํ•˜์ž!

 

์ผ๋‹จ ๊ฐ„๋‹จํ•œ ์ดํ•ด๋Š” ์—ฌ๊ธฐ๊นŒ์ง€ํ•˜๊ณ  ๋‹ค์‹œ ์ฝ”๋“œ๋กœ ๋Œ์•„์™€๋ณด๊ฒ ๋‹ค.

์ž์„ธํ•œ ๋‚ด์šฉ์€ ๋ฆฌ๋•์Šค๋ฅผ ์ •๋ฆฌํ•œ ๊ธ€์„ ํฌ์ŠคํŠธํ•˜๋ฉด์„œ ์ •๋ฆฌํ•˜๊ฒ ๋‹ค!!

 


์ด ์ฝ”๋“œ์—์„œ๋Š” state ์™€ dispatch ๋ฅผ Context ํ†ตํ•˜์—ฌ ๋‹ค๋ฅธ ์ปดํฌ๋„ŒํŠธ์—์„œ ๋ฐ”๋กœ ์‚ฌ์šฉ ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค„ํ…๋ฐ, ์šฐ๋ฆฌ๋Š” ํ•˜๋‚˜์˜ Context ๋ฅผ ๋งŒ๋“ค์–ด์„œ state ์™€ dispatch ๋ฅผ ํ•จ๊ป˜ ๋„ฃ์–ด์ฃผ๋Š” ๋Œ€์‹ ์—, ๋‘๊ฐœ์˜ Context ๋ฅผ ๋งŒ๋“ค์–ด์„œ ๋”ฐ๋กœ ๋”ฐ๋กœ ๋„ฃ์–ด์ค€๋‹ค. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด dispatch ๋งŒ ํ•„์š”ํ•œ ์ปดํฌ๋„ŒํŠธ์—์„œ ๋ถˆํ•„์š”ํ•œ ๋ Œ๋”๋ง์„ ๋ฐฉ์ง€ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ถ”๊ฐ€์ ์œผ๋กœ, ์‚ฌ์šฉํ•˜๊ฒŒ ๋˜๋Š” ๊ณผ์ •์—์„œ ๋”์šฑ ํŽธ๋ฆฌํ•˜๋‹ค๊ณ  ํ•œ๋‹ค.

 

 

TodoContext.js

import React, { useReducer, createContext, useContext, useRef } from 'react';

const initialTodos = [
  {
    id: 1,
    text: 'ํ”„๋กœ์ ํŠธ ์ƒ์„ฑํ•˜๊ธฐ',
    done: true
  },
  {
    id: 2,
    text: '์ปดํฌ๋„ŒํŠธ ์Šคํƒ€์ผ๋งํ•˜๊ธฐ',
    done: true
  },
  {
    id: 3,
    text: 'Context ๋งŒ๋“ค๊ธฐ',
    done: false
  },
  {
    id: 4,
    text: '๊ธฐ๋Šฅ ๊ตฌํ˜„ํ•˜๊ธฐ',
    done: false
  }
];

function todoReducer(state, action) {
  switch (action.type) {
    case 'CREATE':
      return state.concat(action.todo);
    case 'TOGGLE':
      return state.map(todo =>
        todo.id === action.id ? { ...todo, done: !todo.done } : todo
      );
    case 'REMOVE':
      return state.filter(todo => todo.id !== action.id);
    default:
      throw new Error(`Unhandled action type: ${action.type}`);
  }
}

const TodoStateContext = createContext();
const TodoDispatchContext = createContext();
const TodoNextIdContext = createContext();

export function TodoProvider({ children }) {
  const [state, dispatch] = useReducer(todoReducer, initialTodos);
  const nextId = useRef(5);

  return (
    <TodoStateContext.Provider value={state}>
      <TodoDispatchContext.Provider value={dispatch}>
        <TodoNextIdContext.Provider value={nextId}>
          {children}
        </TodoNextIdContext.Provider>
      </TodoDispatchContext.Provider>
    </TodoStateContext.Provider>
  );
}

export function useTodoState() {
  return useContext(TodoStateContext);
}

export function useTodoDispatch() {
  return useContext(TodoDispatchContext);
}

export function useTodoNextId() {
  return useContext(TodoNextIdContext);
}

context์—์„œ ์‚ฌ์šฉํ•  ๊ฐ’์„ ์ง€์ •ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” Provider์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ Œ๋”๋งํ•˜๊ณ  value๋ฅผ ์ •ํ•ด์ฃผ๋ฉด๋œ๋‹ค.

<TodoDispatchContext.Provider value={dispatch}>
   {children}
</TodoDispatchContext.Provider>

 

์ด ์ฝ”๋“œ์ฒ˜๋Ÿผ๋ง์ด๋‹ค.

๊ทธ๋ฆฌ๊ณ  props๋กœ ๋ฐ›์•„์˜จ children๊ฐ’์„ ๋‚ด๋ถ€์— ๋ Œ๋”๋งํ•ด์ฃผ๋ฉด ๋œ๋‹ค.

 

TodoContext ์ฝ”๋“œ๋Š” useConext๋ฅผ 3๊ฐœ๋กœ ๋ถ„๋ฆฌํ–ˆ๋‹ค.(State, Dispatch, nextId)

useContext๋กœ ํ•ด๋‹น context๋ฅผ ๋„ฃ์–ด์ค€๋‹ค.

 

import { useTodoState } from '../TodoContext';
import { useTodoDispatch } from '../TodoContext';
...
 /* ์ปค์Šคํ…€ ์ ์šฉ : ์ปค์Šคํ…€ ํ•œ ํ•จ์ˆ˜๋กœ ๋ฐ”๋กœ ์‚ฌ์šฉ ๊ฐ€๋Šฅ */
 const todos = useTodoState();
 const dispatch = useTodoDispatch();

 /* ์ปค์Šคํ…€ ๋ฏธ์ ์šฉ : Context์ž์ฒด๋ฅผ useContext์˜ ์ธ์ž๋กœ ๋„ฃ์Œ */
 const todos = useContext(TodoStateContext);
 const dispatch = useContext(TodoDispatchContext);

useTodoState, useTodoDispatch๋“ฑ์„ ์‚ฌ์šฉํ•  ๋•Œ,  useContext ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ปค์Šคํ…€ Hook ์„ ๋งŒ๋“ค์–ด์„œ ๋‚ด๋ณด๋‚ด์ฃผ๋Š” ๋ฐฉ๋ฒ•๊ณผ ์ปค์Šคํ…€ํ•œ ํ•จ์ˆ˜๋ฅผ ๋ฐ”๋กœ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ• 2๊ฐ€์ง€๊ฐ€ ์žˆ๋Š”๋ฐ ์œ„์˜ ์ฝ”๋“œ์™€ ๊ฐ™์ด ์ปค์Šคํ…€์„ ์ ์šฉํ•˜๊ณ  ์•ˆํ•˜๊ณ ์— ๋”ฐ๋ผ ๋‹ฌ๋ผ์ง„๋‹ค.

 


์™„์ „ํžˆ ๋‹ค ์ดํ•ดํ•ด๋ณด๋ ค๊ณ ํ–ˆ๋Š”๋ฐ ์•„์ง ๋ถ€์กฑํ•˜๊ฒŒ๋งŒ ๋Š๊ปด์ง„๋‹ค. ๋นจ๋ฆฌ ๋ฆฌ๋•์Šค ๊ด€๋ จ ํฌ์ŠคํŠธ๋ฅผ ์˜ฌ๋ ค์„œ ๋” ์™„๋ฒฝํžˆ ์ดํ•ดํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ด์•ผ๊ฒ ๋‹ค๊ณ  ์ƒ๊ฐํ•˜๊ฒŒ ๋๋‹ค.๐Ÿ˜ฅ

 

728x90