todo 작성, 삭제 후 데이터 정합성 갖추기

히진로그·2022년 9월 25일
0

mini-project

목록 보기
23/28
post-thumbnail

데이터를 새로 만들거나, 기존 데이터를 삭제할 때 실시간으로 반영되는 것이 아니라,
새로고침을 해줘야만 데이터가 변경되었다.

데이터 추가 후 실시간 반영안되는 문제

처음 구현했을 때는 실시간 반영이 잘 되었는데, 여기에서 문제점을 발견했다.
TodoList CRUD 구현하기②에서 썼던 내용을 보면 알 수 있는데, 바로 무한 렌더링이 생긴다는 점이다.

지금 Context api로 상태들을 관리하고 있으니까, 그럼 이 문제도 Context api를 사용해서 해결해볼까 하는 생각이 들었다.

새로운 변수 create의 초깃값으로 false값을 주고 todo를 작성할 때마다 dispatch함수를 사용해서 true로 바꿔주고, todo를 받아오는 로직에서 의존성 배열의 값으로 create를 넣어주면 create값이 바뀌는 걸 감시하고 있다가 todo가 생성되어 create값이 true로 바뀌면 새로운 todo를 받아와 실시간 업데이트를 구현할 수 있다.

// Context 초깃값 설정

const GlobalContextProvider = ({ children }) => {
  const initialToken = localStorage.getItem('token');
  const [state, dispatch] = useReducer(globalReducer, {
    token: initialToken,
    id: null,
    create: false,
  });

  return (
    <GlobalContext.Provider value={{ ...state, dispatch }}>
      {children}
    </GlobalContext.Provider>
  );
};
// todo 작성하는 로직에 추가한 dispatch함수

 const createTodo = async (title, detail) => {
    try {
      await axios.post(
        'http://localhost:8080/todos',
        {
          title: title,
          content: detail,
        },
        {
          headers: {
            Authorization: token,
          },
        }
      );
      dispatch({ type: 'create', payload: true });
    } catch (error) {
      console.log(error);
    }
  };
// create의 값을 감시하는 코드👀

  useEffect(() => {
    token && getTodo();
  }, [create]);

이 방법의 문제점은 create는 초깃값에서 한 번 true로 변경되면 다시는 값이 변경되지 않기 때문에(true -> true) 의존성 배열에서 create의 변경을 캐치할 수가 없다는 것이다. 실시간 반영은 한 번만 이루어진다.

그럼 초깃값을 설정해줄 때 바로 false값을 넣는 게 아니라 새로 변수를 만들어 false값을 넣어주고 그 변수를 초깃값으로 설정하면 어떠려나 하는 생각이 들었다.
그래서 !변수해주면 되는 거 아닌가 했지만 안되지 그 변수를 어떻게 가지고 올 거야 너.😊

그리고 마지막 방법으로 해결했다.! create의 값이 계속 변하게 해야 하기 때문에 중복될 가능성이 있는 데이터를 dispatch함수의 payload로 넣어줄 수는 없었다. 처음에는 todo를 작성할 때의 title을 사용할까 했지만 혹시나 제목을 같게 쓸 경우도 있으니까 제외했다. todo를 작성할 때마다 글의 고유 id도 같이 생성된다. 이 id를 payload값으로 넣어 매번 글이 작성될 때마다 create의 값을 변경해주기로 했다.

// todo 작성하는 로직 payload에 글의 id를 넣어주었다.

  const createTodo = async (title, detail) => {
    try {
      const response = await axios.post(
        'http://localhost:8080/todos',
        {
          title: title,
          content: detail,
        },
        {
          headers: {
            Authorization: token,
          },
        }
      );
      dispatch({ type: 'create', payload: response.data.data.id });
    } catch (error) {
      console.log(error);
    }
  };

(투두를 작성하면 input창을 비우는 로직을 디테일 수정 리스트에 추가해야겠다.)

데이터 삭제 후 실시간 반영안되는 문제

todo 데이터를 삭제 후 새로 고침을 하지 않으면 반영되지 않는 문제를 수정했다.
수정한 방법은 데이터 작성 후 일어나는 문제를 해결한 방법과 똑같다.
globalReducer함수에 새로운 delete case를 추가하고,
todo를 삭제하는 로직에서 dispatch함수를 실행해 id값에 null을 준다.
todoDetail이 받아와 지는 코드에서 클릭된 글의 고유 id를 받아와서 axios요청을 보내기 때문에 null 값으로 변경해 axios요청이 일어나지 않도록 한다.

// TodoDetail 컴포넌트 todoDetail을 받아오는 함수를 
// useEffect안에서 실행하고 id 값을 의존성 배열에 추가하여
// id 값이 바뀔 때마다 todo의 제목과 내용을 받아온다.

  useEffect(() => {
    id && getTodoDetail();
  }, [id]);

TodoTitle컴포넌트에서도 todo가 삭제되었다는 사실을 알아야 하기 때문에 여기서도 id값을 가져와서 의존성 배열에 추가해준다.

// TodoTitle 컴포넌트
// todo가 새로 생성될 때, 삭제될 때마다 다시 effect가 실행된다.

  useEffect(() => {
    token && getTodo();
  }, [create, id]);

근데 이젠 다른 문제가 생겼다.
todo가 여러 개 있을 때 그중 하나를 삭제하고 다른 todo를 클릭하면 삭제된 todo의 제목과 내용이 그대로 떴다가 1초 뒤 클릭한 todo 제목과 내용이 뜬다.

왜 이런 걸까?
처음 선택된 id는 세 번째 글의 id이고 삭제 버튼을 누르면 id에는 null값이 할당된다. id값이 바뀌고 useEffect 안에서 id값이 null이기 때문에 && 뒤의getTodoDetail함수는 실행되지 않는다.
다음 두 번째 리스트를 부르면 null값인 id변수에 두 번째 글 id가 들어오고 getTodoDetail함수가 실행된다.

근데 왜 삭제한 todo의 내용이 먼저 떴다가 클릭된 todo의 내용이 들어오는 걸까?🤔

0개의 댓글