useReducer, useContext

렐루·2024년 5월 20일

1. 공식문서 내용 정리

https://ko.react.dev/learn/scaling-up-with-reducer-and-context

  • Reducer와 context를 결합해서 컴포넌트가 상위 state를 읽고 수정할 수 있도록 할 수 있습니다.
  • State와 dispatch 함수를 하위 컴포넌트들에 제공하는 방법
    1. 두 개의 context를 만듭니다(각각 state와 dispatch 함수를 위한 것).
    2. Reducer를 사용하는 컴포넌트에 두 context를 모두 제공합니다.
    3. 하위 컴포넌트들에서 필요한 context를 사용합니다.
  • 더 나아가 하나의 파일로 합쳐서 컴포넌트들을 정리할 수 있습니다.
    • Context를 제공하는 TasksProvider 같은 컴포넌트를 내보낼 수 있습니다.
    • 바로 사용할 수 있도록 useTasks와 useTasksDispatch 같은 사용자 Hook을 내보낼 수 있습니다.
  • context-reducer 조합을 앱에 여러 개 만들 수 있습니다.

컴포넌트가 조금만 복잡해져도 State가 내려줘야할 깊이가 매우 깊어집니다.
또한 종류가 조금만 늘어나도 같은 코드를 많이 반복해줘야 합니다.

그럴 때 Context를 사용해서 부분적인 전역을 만들 수 있습니다.

2. 예시코드

// App.jsx
import AddTask from './AddTask.js';
import TaskList from './TaskList.js';
import { TasksProvider } from './TasksContext.js';

export default function TaskApp() {
  return (
    <TasksProvider>
      <h1>Day off in Kyoto</h1>
      <AddTask />
      <TaskList />
    </TasksProvider>
  );
}


// TasksContext.jsx
import { createContext, useContext, useReducer } from 'react';

const TasksContext = createContext(null);

const TasksDispatchContext = createContext(null);

export function TasksProvider({ children }) {
  const [tasks, dispatch] = useReducer(
    tasksReducer,
    initialTasks
  );

  return (
    <TasksContext.Provider value={tasks}>
      <TasksDispatchContext.Provider value={dispatch}>
        {children}
      </TasksDispatchContext.Provider>
    </TasksContext.Provider>
  );
}

export function useTasks() {
  return useContext(TasksContext);
}

export function useTasksDispatch() {
  return useContext(TasksDispatchContext);
}

function tasksReducer(tasks, action) {
  switch (action.type) {
    case 'added': {
      return [...tasks, {
        id: action.id,
        text: action.text,
        done: false
      }];
    }
    case 'changed': {
      return tasks.map(t => {
        if (t.id === action.task.id) {
          return action.task;
        } else {
          return t;
        }
      });
    }
    case 'deleted': {
      return tasks.filter(t => t.id !== action.id);
    }
    default: {
      throw Error('Unknown action: ' + action.type);
    }
  }
}

const initialTasks = [
  { id: 0, text: 'Philosopher’s Path', done: true },
  { id: 1, text: 'Visit the temple', done: false },
  { id: 2, text: 'Drink matcha', done: false }
];

3. 코드 내용

위의 코드는 useReducer와 useContext를 하나의 파일에서 관리해주는 코드입니다.

useReducer의 dispatch 함수와 state
useContext의 provider, context 값을 한 파일에서 정의하여
export로 깔끔하게 내보내고 있습니다.

각각 필요한 부분에서 해당 내용들을 정의했더라면 수정사항이나 내용을 상기할 필요가 발생할 경우, 코드들을 읽어가면서 찾아야 했을 것입니다.

하지만 한 파일에서 깔끔하게 관리함으로써 유지보수와 코드 재사용성을 높이고 있습니다.

기존의 코드 사진입니다.

위의 사진에서 각각의 파일들에서 불러오면 훅들입니다.
이런 훅들과 함수들을 한 파일에서 관리해주게 됩니다.
간단하게 함수로 정의하여 불러오기만 하면 됩니다!!

감사합니다!!!

profile
프론트 공부중입니다!

0개의 댓글