프론트엔드 인턴쉽에서 투두리스트 앱을 만드는 과제를 하던 중 UX를 해치는 부분을 발견했다.
// 기존 코드
const updateTodoHandler = () => {
setIsUpdate(() => true);
const newTodo = newTodoRef.current?.value;
if (isInputValid(newTodo)) return;
onUpdate(todoItem.id, newTodo, todoItem.isCompleted);
setIsUpdate(() => false);
};
const onUpdateTodo = async (todoId: number, todoText: string, isCompleted: boolean) => {
await updateTodo(todoId, todoText, isCompleted);
onReadTodo();
};
그건 바로 Todo를 업데이트할 때 깜빡인다는 것이다.
사실 투두리스트의 핵심 기능중 하나인 업데이트할 때 깜빡이는 버그는 꽤나 큰 문제로 다가왔는데
이 문제를 해결하기 위해선 일단 문제의 원인을 찾아야 했다.
우리의 코드는 업데이트하면 update API호출을 하고 바로 다음에 get API 호출을 한 다음에 사용자에게 보여준다.
이 과정에서 깜빡이게 되는건데
이걸 고치려면 사용자가 업데이트를 했을 때 사용자 화면에서만 바꿔주면 된다.
하지만 그렇게 되면 서버에서 오류가 있거나 update에 실패하게 되더라도 사용자는 인지하지 못한 채 서비스를 이용하게 된다.
그래서 기존 코드는 그것을 방지하기 위해서 항상 최신의 상태를 유지하려고 update후 바로 get API호출해서 다시 그린다.
이러한 문제점을 개선하기 위해 고민했는데 해결방법으로 생각해 낸 게 우선 사용자의 상태는 변경시켜 놓고, 그러고 나서 update의 API호출을 하는 것이다.
그렇게 되면 사용자는 즉시 수정이 반영된 상태를 볼 수 있을 것이다.
그렇지만 최신상태를 반영할 수 없기 때문에 API호출에서 응답으로 에러가 온다면 다시 롤백시키는 로직을 추가하거나 경고창을 띄워서 문제를 해결하면 깔끔하게 해결할 수 있을 거 같다.
// 개선 코드
const updateTodoHandler = () => {
setIsUpdate(() => true);
const newTodo = newTodoRef.current?.value;
if (isInputValid(newTodo)) return;
onUpdate(todoItem.id, newTodo, todoItem.isCompleted);
setIsUpdate(() => false);
};
// 추가
const updateTodoState = (todoId: number, todoText: string, isCompleted: boolean) => {
setTodoItems((prevTodoItems) =>
prevTodoItems.map((todo) =>
todo.id === todoId ? { ...todo, todo: todoText, isCompleted } : todo
)
);
};
const onUpdateTodo = async (todoId: number, todoText: string, isCompleted: boolean) => {
updateTodoState(todoId, todoText, isCompleted);
await updateTodo(todoId, todoText, isCompleted);
onReadTodo();
};
추가로 다른 팀원분이 제시한 방법이 있었는데
// 또 다른 개선 코드
const updateTodoHandler = async () => {
setIsUpdate(() => true);
const newTodo = newTodoRef.current?.value;
if (isInputValid(newTodo)) return;
await onUpdate(todoItem.id, newTodo, todoItem.isCompleted);
setIsUpdate(() => false);
};
const onUpdateTodo = async (todoId: number, todoText: string, isCompleted: boolean) => {
// updateTodoState(todoId, todoText, isCompleted);
await updateTodo(todoId, todoText, isCompleted);
await onReadTodo();
};
비동기 순서를 통제해서 호출 순서를 바꾸는 것이다.
이렇게 되면 업데이트 호출에 대한 응답을 받은 이후에 get으로 받은 응답을 그리기 때문에 깜빡이는 문제를 해결할 수 있다.
내가 생각한 방법도 좋지만 이러한 방법도 바로 같이 떠올릴 수 있도록 경험치를 쌓아야겠다.
'FrontEnd > React' 카테고리의 다른 글
Next.js 14 완벽 번역 (1) | 2023.10.27 |
---|---|
리액트에서 ...state 와 prev => ...prev 의 차이 (0) | 2023.04.25 |
최초 로그인시 토큰이 null로 보내지는 버그 (0) | 2023.04.16 |
Create-React-App는 무엇을 설치해주나? (0) | 2023.04.12 |
BrowserRouter vs HashRouter ? (0) | 2023.04.12 |