todo 수정을 취소해도 수정이 된다?! (제목 업데이트는 또 왜 한 박자 느리냐 🙃)

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

mini-project

목록 보기
25/28
post-thumbnail

todo 수정을 하는 로직과 todo detail을 불러오는 로직이 동일한 TodoDetail컴포넌트에 있다.

todo 제목이 클릭되었을 때 todo detail을 불러와야 하고 이때 사용했던 state들이 title과 detail이다.

export const TodoDetail = () => {
  const [title, setTitle] = useState('');
  const [detail, setDetail] = useState('');
  
    useEffect(() => {
    id &&
      getTodoDetail(id, token).then((result) => {
        setTitle(result.data.data.title);
        setDetail(result.data.data.content);
      });
  }, [id]);

  //... 다른 많은 코드들 
    <EditModal isTrue={show}>
          <header>
            <h2>Rewrite your todo</h2>
          </header>
          <form>
            <label htmlFor="title">TODO</label>
            <input
              type="text"
              id="title"
              value={title}
              onChange={newTitleDataHandler}
            />

            <label htmlFor="detail">DETAIL</label>
            <input
              type="text"
              id="detail"
              value={detail}
              onChange={newDetaildDataHandler}
            />
          </form>
          <footer>
            <button onClick={hideModalHandler}>UNDO</button>
            <button onClick={onTodoEditHandler}>DONE</button>
          </footer>
        </EditModal>
}

EDIT버튼을 클릭하면 수정할 수 있는 모달이 뜨는데, 이때 클릭된 todo의 제목과 내용을 가져와야 한다. 그리고 수정하면 즉시 반영되도록 해야 한다.
수정 모달을 띄우면서 클릭한 todo의 제목과 내용을 어떻게 가져올 수 있을까.. 고민했다. 그리고 생각해낸 게 title과 detail state값을 그대로 쓰면 되지 않을까??

잘 동작한다. 고 생각했는데 내가 간과한 부분 두 가지가 있었다.

첫 번째는 바로 todo의 title이다.

todo title을 가져오는 것과 수정 모달에서 todo title을 수정하는 것은 연결되어있지 않기 때문에 제목을 수정하면 새로고침 하거나 다른 리스트가 있을 경우 다른 리스트를 한 번 클릭해야 변경된다.

다른 리스트를 클릭할 때 id값이 변하고 id값을 감시하고 있는 useEffect안에서 todo title을 가져오는 함수가 재 실행되기 때문이다.
이 부분은 useReduce함수에 새로운 case를 추가해서 해결할 수도 있을 것 같고, todoDetail에서 사용하는 모달 창을 열고 닫는 boolean 값의 state를 감시하고 있다가 창을 닫을 때 state가 변하면서 리액트가 새로 렌더링 되면서 저쪽 컴포넌트도 새로 getTodoTitle을 하도록 하는 방법을 쓸 수도 있을 것 같다.(후자 방법은 안되네. 아 이거 또 당연한 내용이네. 리액트에서는 변경된 부분만 업데이트하기 때문에 당연히 저쪽 컴포넌트는 상관이 없지😐)
해결한 과정 보러 가기👀

내가 간과한 부분 두 번째는 UNDO버튼을 클릭해도 수정이 된다는 점이다.


UNDO버튼을 클릭했지만 내가 새로 작성한 부분이 추가된 것을 볼 수 있다. 왜 이런 일이 일어났을까.
todo detail을 불러오는 로직에서 사용한 state값과 동일한 값을 사용하고 onChange함수 안에서 setState를 써서 state값을 업데이트해주고 있기 때문이다.
todo 수정을 위한 새 state를 만들어서 써야겠다고 해결방법을 생각해두긴 했는데, 생각대로 되려나?

해결했다. 해결은 했는데... 🤔

해결은 했는데 왜 뭔가 아쉬울까
수정될 내용을 위해 새로운 state를 만들었고, 처음에는 기존 title, detail변수를 새로운 state의 초깃값으로 넣어줬다.

export const TodoDetail = () => {
  const [title, setTitle] = useState('');
  const [detail, setDetail] = useState('');
  const [show, setShow] = useState(false);
  const [newTitle, setNewTitle] = useState(title);
  const [newDetail, setNewDetail] = useState(detail);
  
  useEffect(() => {
  	id &&
      getTodoDetail(id, token).then((result) => {
        setTitle(result.data.data.title);
        setDetail(result.data.data.content);
      });
  }, [id]);
}

나는 이게 제대로 될 줄 알았는데 newTitle과 newDetail 값이 클릭된 title과 detail값으로 변경되지 않더라. title과 detail의 초기값인 ''만 들어옴.
근데 😆 당연한 거 아닐까? newTitle, newDetail에 초기값으로 title 넣어주면 뭐해 setNewTitle, setNewDetail로 바꾸지 않으면 안 바뀌는데...

그래서 다른 방법 시도!

export const TodoDetail = () => {
  const [title, setTitle] = useState('');
  const [detail, setDetail] = useState('');
  const [show, setShow] = useState(false);
  const [newTitle, setNewTitle] = useState('');
  const [newDetail, setNewDetail] = useState('');
  
  useEffect(() => {
  	id &&
      getTodoDetail(id, token).then((result) => {
        setTitle(result.data.data.title);
        setDetail(result.data.data.content);
        setNewTitle(result.data.data.title);
        setNewDetail(result.data.data.content);
      });
  }, [id]);
}

아예 그냥 newTitle, newDetail state도 클릭된 todo의 제목과 내용을 받아오도록 해줬다.
그리고 수정 모달 input값의 value로 newTitle과 newDetail을 넣어주었다.
이제 문제점은 수정은 되는데 실시간 반영이 안 된다.

현재 useEffect에서는 id값만 감시하고 있기 때문에 수정을 해도 id가 바뀌지 않으니까 getTodoDetail함수가 다시 실행되지 않는다.

현재 아무 상태도 새로 만들지 않고 가능한 해결 방법으로 모달을 띄움의 여부로 설정해둔 show state를 의존성 배열에 추가했다. 모달을 띄우고 수정 후 DONE 버튼을 클릭하면 show의 상태가 바뀌고 useEffect안의 함수들이 다시 실행되면서 title과 detail값이 업데이트되고 수정된 내용이 바로바로 반영된다.(첫 번째에서 지적했듯이 제목은 별개.)
이 방법의 안 좋은 점은 필요 없는 렌더링 일어난다는 것이다.

0개의 댓글