리엑트 Todo List 만들기 3 - Context API를 이용해 상태 관리하기

리엑트 Todo List 만들기 3 - Context API를 이용해 상태 관리하기

Context API 사용 설정하기

Reducer 생성

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}`);
}
}

Conext API 적용하기

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>
);
}

Context 사용을 위한 Custom Hook 생성

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

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

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

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 API 적용하기

App.js

import React from "react";
import { createGlobalStyle } from "styled-components";
import TodoTemplate from "./components/TodoTemplate";
import TodoHead from "./components/TodoHead";
import TodoList from "./components/TodoList";
import TodoCreate from "./components/TodoCreate";
import { TodoProvider } from "./TodoContext";

const GlobalStyle = createGlobalStyle`
body {
background: #e9ecef;
}
`;

function App() {
return (
<TodoProvider>
<GlobalStyle />
<TodoTemplate>
<TodoHead />
<TodoList />
<TodoCreate />
</TodoTemplate>
</TodoProvider>
);
}

export default App;
Share