Next.js+axios+json-server로 TodoList만들기

정소현·2024년 10월 11일

Next.js

목록 보기
5/5

github 바로가기

  • Next.js+axios+json-server를 활용하여 TodoList를 만들어보았다.
  1. Next.js 폴더생성
npx create-next-app@latest
  1. axios 추가
yarn add axios
  1. json-server에 todoList mocdata를 저장하기 위해 설치
yarn add json-server
  1. package.json에 yarn server로 포트 추가
 "server":  "yarn json-server db.json --port 4000"
  1. root에 db.json을 생성 후 데이터 집어넣기
{
  "todos": [
    { "id": "1", "title": "TODO1", "contents": "sample contents", "isDone": true },
    { "id": "2", "title": "TODO2", "contents": "sample contents", "isDone": false }
  ],
}
  1. src > app > todo 폴더생성 > page.tsx
  2. src > component 폴더생성, src > type 폴더생성
  3. src > type > todo.ts 에 todo type설정
export interface Todo {
  id: number;
  title: string;
  contents: string;
  isDone: boolean;
}
  1. src>utils>api
    json server로부터 axios를 사용해 데이터를 불러오고, 추가, 삭제, 수정할 수 있게 로직을 만들었다.

☘️ 데이터 가져오기

 export const getTodo = async () => {
  try {
    const res = await axios.get(BASEURL);
    return res.data;
  } catch (error) {
    console.log("fetch error:", error);
  }
};

☘️ 데이터 추가하기

export const addTodo = async (newTodo: {
  title: string;
  contents: string;
  isDone: boolean;
}) => {
  try {
    const res = await axios.post(BASEURL, newTodo);
    return res.data;
  } catch (error) {
    console.log("addError:", error);
  }
};

☘️ 데이터 수정하기

export const patchTodo = async ({
  id,
  isDone,
}: Pick<Todo, "id" | "isDone">) => {
  try {
    const res = await axios.patch(`${BASEURL}/${id}`, { isDone: !isDone });
    return res.data;
  } catch (error) {
    console.log(error);
  }
};```

☘️ 데이터 삭제하기
```ts
export const deleteTodo = async (id: number) => {
  try {
    const res = await axios.delete(`${BASEURL}/${id}`);
    return res.data;
  } catch (error) {
    console.log("deleteError:", error);
  }
};

💥 API 연결 트러블슈팅

  1. todo> page.tsx에서 기본 레이아웃을 꾸며준 후 데이터로지들을 작성해주었다.
  • 아직 type을 다루는 게 익숙하지 않아 많은 오류들을 경험했다.

1. Event type

문제 : 데이터를 추가하는 로직을 작성한 후 이벤트에도 type을 설정해야하는 것을 알았다.
해결 : e: React.FormEvent 추가 후 any에서 벗어남!

2. 객체 형태의 type Error

문제 : {title:string; contents:string;} 형식의 인수는
{title:string; contents:string; isDone : boolean}
is Done속성이 없다는 typeError가 났다.
해결 : 내가 api를 호출하는 로직에서 isDone까지 로직을 작성하였는데
page.tsx에서 작성하지 않아 생긴 문제
내가 놓치고 가는 부분들을 확실하게 typescript에서 잡아주는 점이 좋았다.

// 데이터 추가하기
  const handleAddTodo = async (e) => {
    e.preventDefault();
    const newTodo = { title, contents };
    const data = await addTodo(newTodo);
    setTodo((prev) => [...prev, data]);
    setTitle("");
    setContents("");
  };

fix ver.

  // 데이터 추가하기
  const handleAddTodo = async (e: React.FormEvent) => {
    e.preventDefault();
    const newTodo = { title, contents, isDone: false };
    const data = await addTodo(newTodo);
    setTodo((prev) => [...prev, data]);
    setTitle("");
    setContents("");
  };

💥 데이터 나타내기 트러블슈팅

문제점 : TodoCard.tsx 컴포넌트를 만들었다.
props로 받아오는 과정에서 type오류가 많이 발생했다.

// 맨 처음 작성한 코드

import { Todo } from "@/type/todo";
import React from "react";
interface TodoProps {
  todo: Todo[];
  onDelete: (id: number) => void;
  onPatch: (id: number, isDone: boolean) => void;
}
const Todocard: <TodoProps> = ({ todo, onDelete, onPatch }) => {
  return (
    <li>
      <p>{todo.title}</p>
    </li>
  );
};

export default Todocard;

맨 처음 작성한 코드에서

  1. props의 type을 붙일 때 React.FC를 붙이지 않아 오류가 났다.
  2. 나는 src > todo > page.tsx 에서 map을 돌려서 해당 컴포넌트를 불러왔는데 props의 type을 지정하는 부분에서 Todo[] 배열 형태로 불러와 오류가 났다.

해결방법

import { Todo } from "@/type/todo";
import React from "react";
interface TodoProps {
  todo: Todo;
  onDelete: (id: number) => void;
  onPatch: (id: number, isDone: boolean) => void;
}
const Todocard: React.FC<TodoProps> = ({ todo, onDelete, onPatch }) => {
  return (
    <li>
      <p>{todo.title}</p>
      <p>{todo.contents}</p>
      <button onClick={() => onDelete(todo.id)}>삭제</button>
      <button onClick={() => onPatch(todo.id, todo.isDone)}>
        {!todo.isDone ? "완료" : "취소"}
      </button>
    </li>
  );
};

export default Todocard;
profile
기술을 넘어 제품의 가치를 만드는 프론트엔드 엔지니어를 지향합니다.

0개의 댓글