개인프로젝트 - todoit 4회차

Seuling·2022년 7월 30일
0

개인프로젝트

목록 보기
4/4
post-thumbnail

220730

  • query 이용 오늘 날짜 보여주기
    - jsonserver api 활용
  • database : doneDateTime 상태 업데이트
    - changeDoneTodoItem, handleClickCheckBtn 함수 구현
    - changeDoneTodoItem 이용시, get put 요청 각각 발생함에따라 changeTodoItem으로 변경
  • dayjs 전역 분리
    - 이전일자, 이후일자 보여줌

query 이용 오늘 날짜 보여주기

jsonserver api 활용


jsonserver 의 기본제공 함수로 query를 처리할 수 있다.
일단, 오늘날짜를 보여줘야겠지?
서버를 키고 : http://localhost:8000/
database의 구조에 따라 보여주기 : todos 보여줘야겠지!
http://localhost:8000/todos?

여기서, createDateTime이 중첩된 형태인데, nested 의 query 어떻게날리지 ??? -> .으로 날리는구나!!

http://localhost:8000/todos?dateTimes.createdDateTime_gte=2022-07-23T00:00:00+09:00&dateTimes.createdDateTime_lte=2022-07-24T00:00:00+09:00
async getDateTodoItems(date: string): Promise<Array<TodoItemType>> {
    const day = dayjs(date);
    const startDate = day.format("YYYY-MM-DD");
    const endDate = day.add(1, "day").format("YYYY-MM-DD");
    const response = await todoAxios.get(
      `/todos?dateTimes.createdDateTime_gte=${startDate}&dateTimes.createdDateTime_lte=${endDate}`
    );
    return response.data;
  }

database : doneDateTime 상태 업데이트

체크버튼을 눌렀을 때, 완료한시간을 db로 보내주고, patch 상태가 바뀌었을 때 화면에 그려주기

changeDoneTodoItem, handleClickCheckBtn 함수 구현

먼저, AxiosTodoService에서 put을 해주는 changeDoneTodoItem 함수 구현

async changeDoneTodoItem(id: number, isDone: boolean): Promise<void> {
    const doneDateTime = isDone ? dayjs().format() : null;
    await todoAxios.patch(`/todos/${id}`, {
      isDone: isDone,
      dateTimes: { doneDateTime: doneDateTime },
    });
  }

위와 아래 동일함! isDone: isDone, doneDateTime: doneDateTime 이렇게 database의 key, value 값이 동일한 경우 아래와 같이 한번만 써줘도 된다!

async changeDoneTodoItem(id: number, isDone: boolean): Promise<void> {
    const doneDateTime = isDone ? dayjs().format() : null;
    // "2022-07-30T20:45:00+09:00"
    await todoAxios.patch(`/todos/${id}`, {
      isDone,
      dateTimes: { doneDateTime },
    });
  }

여기서의 문제점 ?
이렇게 하고보니, dateTimes 가 변경되는데 nested되어서 createdDateTime은 빈값이 들어가는 문제점 발생!!

그럼 어떻게해결하지 ?
createdDateTime도 넣어주면되지않을까 ?
그럼 get을 다시 한번 해주면 되지않을까 ? -> 해결!

async changeDoneTodoItem(id: number, isDone: boolean, doneDateTime: string | undefined): Promise<void> {
    const todoItem = await this.getTodoItem(id);
    //put 을 할때 todoItem에 isDone 상태에 따라 Donedatetime과 함께 다같이 업데이트 해주면됨
    await todoAxios.put(`/todos/${id}`, {
      ...todoItem,
      isDone,
      dateTimes: { ...todoItem.dateTimes, doneDateTime },
    });
  }

<TodoItem/>handleClickCheckBtnchangeDoneTodoItem 함수 연결!
문제점?
서버로 요청은 잘 가고있지만, 새로고침해야지만 다시 렌더 되는 이슈 발생

리액트에서 렌더링이 되는 기준이 뭐지??????
리액트에서 렌더링이란, 컴포넌트가 현재 propsstate의 상태에 기초하여 UI를 어떻게 구성할지 컴포넌트에게 요청하는 작업을 의미한다.

handleClickCheckBtn 을 눌렀을 때 왜 체크아이콘은 바뀌고, endtime의 text는 바뀌지 않는것일까?
확인해봐야하는 지점,
handleClickCheckBtn
ItemBtn
Text
TodoItem 컴포넌트에서 item에 따른 state를 다시 todoItem을 해주지!

const [todoItem, setTodoItem] = useState(item);

그렇다면, handleClickCheckBtn에서 상태가 제대로 바뀌고 있는가 ??

계속 같은 값이 눌림!! -> 즉, 안바뀌고있다!
그럼 언제 어떻게 바뀌지 ?
changeTodoItem 을 할 때 doneDateTime을 같이 바꿔줘야하는데 어떻게 같이 바꾸지?
아예 doneDateTimehandleClickCheckBtn내에서 만들어주면 되지않을까? put을 보낼때 같이보내면 되는거 아닌가 ??? -> OK

handleClickCheckBtn시 리렌더링이 안되는 이유는 ? {…todoItem}에 + isDone 부분만 업데이트를 해줬기때문에!
doneDateTime 을 똑같이 변경해주면 되겠지!!

changeDoneTodoItem 이용시, get put 요청 각각 발생함에따라 changeTodoItem으로 변경

chanegeTodoItem()이 아니라, changeDoneTodoItem()을 함으로써,handleClickCheckBtn 시마다 불필요한 get, put 두번의 요청이 있었다.

따라서 한번만 요청해도 되지않을까 ? 라는 생각에 changeTodoItem으로 요청을 바꿔주었고,

async changeDoneTodoItem(id: number, isDone: boolean, doneDateTime: string | undefined): Promise<void> {
    const todoItem = await this.getTodoItem(id);
    //put 을 할때 todoItem에 isDone 상태에 따라 Donedatetime과 함께 다같이 업데이트 해주면됨
    await todoAxios.put(`/todos/${id}`, {
      ...todoItem,
      isDone,
      dateTimes: { ...todoItem.dateTimes, doneDateTime },
    });
}

async changeTodoItem(item: TodoItemType): Promise<void> {
    await todoAxios.put(`/todos/${item.id}`, item);
}


nextTodoItem의 전체의 값을 한번에 보내주면 put으로 한번에 업데이트 됨을 알 수 있었음!

const handleClickCheckBtn = () => {
    const toIsDone = !todoItem.isDone;
    const doneDateTime = toIsDone ? dayjs().format() : undefined;
    const nextTodoItem = {
      ...todoItem,
      isDone: toIsDone,
      dateTimes: { ...todoItem.dateTimes, doneDateTime },
    };

    const temp = { ...todoItem };
    todoService.changeTodoItem(nextTodoItem).catch(() => {
      setTodoItem(temp);
    });
    setTodoItem(nextTodoItem);
  };

리액트에서 전체요청을 줄이기위해서는 ? 전체 데이터를 통으로 가지고 있다가, view부분은 복사한값으로 렌더링을 해주면 된다!

dayjs 전역 분리

시간이 한번에 변경되려면 각자 관리하는게 아니라 한곳에서 관리해야하지 않을까?
메인페이지에서 관리 (→ 추후 리코일로 변경예정)

//App.tsx
function App() {
  dayjs.locale("ko");
}
//Mainpage
const Mainpage = (props: Props) => {
    const [today, setToday] = useState(dayjs());
  return (
 )
}

이전일자, 이후일자 보여줌

subtract , add함수 활용

<DayBtnContainer>
        <IconBtn
          handleOnClick={() => {
            setToday(today.subtract(1, "d"));
          }}
        >
          이전일자보기
        </IconBtn>
        <IconBtn
          handleOnClick={() => {
            setToday(today.add(1, "d"));
          }}
        >
          다음일자보기
        </IconBtn>
      </DayBtnContainer>
profile
프론트엔드 개발자 항상 뭘 하고있는 슬링

0개의 댓글