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;
}
체크버튼을 눌렀을 때, 완료한시간을 db로 보내주고, patch 상태가 바뀌었을 때 화면에 그려주기
먼저, 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/>
의 handleClickCheckBtn
에 changeDoneTodoItem
함수 연결!
문제점?
서버로 요청은 잘 가고있지만, 새로고침해야지만 다시 렌더 되는 이슈 발생
리액트에서 렌더링이 되는 기준이 뭐지??????
리액트에서 렌더링이란, 컴포넌트가 현재 props와 state의 상태에 기초하여 UI를 어떻게 구성할지 컴포넌트에게 요청하는 작업을 의미한다.
handleClickCheckBtn 을 눌렀을 때 왜 체크아이콘은 바뀌고, endtime의 text는 바뀌지 않는것일까?
확인해봐야하는 지점,
handleClickCheckBtn
ItemBtn
Text
TodoItem 컴포넌트에서 item에 따른 state를 다시 todoItem을 해주지!
const [todoItem, setTodoItem] = useState(item);
그렇다면, handleClickCheckBtn
에서 상태가 제대로 바뀌고 있는가 ??
계속 같은 값이 눌림!! -> 즉, 안바뀌고있다!
그럼 언제 어떻게 바뀌지 ?
changeTodoItem
을 할 때 doneDateTime
을 같이 바꿔줘야하는데 어떻게 같이 바꾸지?
아예 doneDateTime
을 handleClickCheckBtn
내에서 만들어주면 되지않을까? put을 보낼때 같이보내면 되는거 아닌가 ??? -> OK
handleClickCheckBtn시 리렌더링이 안되는 이유는 ? {…todoItem}에 + isDone 부분만 업데이트를 해줬기때문에!
doneDateTime 을 똑같이 변경해주면 되겠지!!
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부분은 복사한값으로 렌더링을 해주면 된다!
시간이 한번에 변경되려면 각자 관리하는게 아니라 한곳에서 관리해야하지 않을까?
메인페이지에서 관리 (→ 추후 리코일로 변경예정)
//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>