[React - TS] TODO APP - useContext 적용

빛트·2022년 5월 25일
1

REACT-TS-TODO

목록 보기
5/6
post-thumbnail

여는 말

TS를 익히기 위해 만들어본 TODO 앱입니다

이번 글에서는 State와 Props로만 구성되어 있던 앱을

context를 이용하도록 수정하는 것을 목표로 합니다


소스

TodoContext.tsx 파일을 생성했습니다

context.tsx

Todo의 타입을 새로 생성한 파일 안으로 옮기고,

context에 사용할 타입과 Context를 생성했습니다

// TodoContext.tsx
import { createContext, SetStateAction } from "react";

export interface ITodo {
  idx: number;
  title: string;
  project: string;
}

interface ITodoContext {
  todos: ITodo[];
  editIdx: number | null;
  setTodos: React.Dispatch<SetStateAction<ITodo[]>>;
  setEditIdx: React.Dispatch<SetStateAction<number | null>>;
}

export const TodoContext = createContext({} as ITodoContext);

TodoList.tsx

todos는 context로 전달되는 setTodos를 이용해 제어될 것입니다

addTodo, updateTodo, deleteTodo 함수를 삭제하고, Provider로 child를 감싸주었습니다

// TodoList.tsx
//...
import { ITodo, TodoContext } from "../contexts/TodoContext";

const TodoList = () => {
  const [todos, setTodos] = useState<ITodo[]>([]);
  const [editIdx, setEditIdx] = useState<number | null>(null);

  const Items = () => {
    return todos.map((item) => {
      if (item.idx === editIdx) {
        return (
          <EditTodo
            idx={item.idx}
            title={item.title}
            project={item.project}
          ></EditTodo>
        );
      } else {
        return (
          <Todo idx={item.idx} title={item.title} project={item.project}></Todo>
        );
      }
    });
  };

  return (
    <div className="todo-list-container">
      <TodoContext.Provider value={{ todos, editIdx, setTodos, setEditIdx }}>
        {Items()}
        <CreateTodo />
      </TodoContext.Provider>
    </div>
  );
};

Todo.tsx

수정 버튼 클릭, 삭제 버튼 클릭 시 동작을 변경합니다

// Todo.tsx
// ...
import { useContext } from "react";
import { TodoContext, ITodo } from "../contexts/TodoContext";

const Todo = (props: ITodo) => {
  const { todos, setTodos, setEditIdx } = useContext(TodoContext);

  const handleClickDeleteBtn = () => {
    const newTodo = todos.filter((item) => {
      return item.idx !== props.idx;
    });
    setTodos(newTodo);
  };

  const handleClickUpdateBtn = () => {
    setEditIdx(props.idx);
  };
  //...
};

CreateTodo.tsx

추가 버튼 클릭 동작을 변경합니다

// CreateTodo.tsx
import { useContext, useState } from "react";
import { TodoContext } from "../contexts/TodoContext";

const CreateTodo = () => {
  const { todos, setTodos } = useContext(TodoContext);
  //...

  const handleClickCreateBtn = () => {
    let todo = { idx: idx, title: title, project: project };
    setTodos([...todos, todo]);
    setIdx(idx + 1);
    setEmpty();
  };
  //...
};

EditTodo.tsx

// EditTodo.tsx
import React, { useContext, useEffect, useState } from "react";
import { TodoContext, ITodo as EditTodoProp } from "../contexts/TodoContext";

const EditTodo = (props: EditTodoProp) => {
  const { todos, setTodos, setEditIdx } = useContext(TodoContext);

  //...

  const handleClickSubmitBtn = () => {
    const newTodo = todos.map((item) => {
      if (item.idx === props.idx) {
        return { idx: props.idx, title, project };
      } else {
        return item;
      }
    });
    setTodos(newTodo);
    setEditIdx(null);
  };
  //...
};

닫는 말

전체 소스 : Github

0개의 댓글