감정일기장 만들기 2 - CRUD 기능 구현 (3) 수정

동화·2023년 3월 9일
0

diary-project

목록 보기
4/8
post-thumbnail

EDIT

데이터 정보 가져오기

먼저 현재 일기의 데이터를 가져올 수 있게 해야함.

<Route path="/edit/:id" element={<Edit />} />

일단 App.js에서 라우트 설정을 해준다. (:id)

useParams를 이용해서 id값을 받아오고,
App.js 에서 useContext에 담아뒀던 다이어리 리스트를 불러온다

Edit

import { useContext } from "react";
import { useNavigate, useParams } from "react-router-dom";
import { DiaryStateContext } from "../App";

const Edit = () => {
  const navigate = useNavigate();
  const { id } = useParams();
  console.log(id);

  const diaryList = useContext(DiaryStateContext);
  console.log(diaryList);

잘 불러와졌는지 확인!

diaryList에 우리가 찾는 id와 일치하는 id를 찾게 되면, 수정하려는 글을 불러오게 함.
이 작업은 Edit 컴포넌트가 마운트 됐을 때 실행할 것이기 때문에 useEffect 사용

  useEffect(() => {
    if (diaryList.length >= 1) {
      const targetDiary = diaryList.find(
        (it) => parseInt(it.id) === parseInt(id)
      );
      console.log(targetDiary);
    }
  }, [id, diaryList]);
  • id가 변해도 / diaryList가 변해도 다른 데이터를 꺼내와야 하기 때문에 둘다 작성
, [id, diaryList]

console.log

번호를 바꿔도 다른 일기를 잘 가지고 온다.

없는 id의 일기

...
      if (targetDiary) {
      } else {
        navigate("/", { replace: true });
      }

글이 6번까지밖에없는데 /edit/9를 입력하면
잘못된 입력이기 때문에, 홈으로 돌아가게 만들어주는 코드 추가.




target state

targetDiary를 저장할 state를 만들어준다.

const [originData, setOriginData] = useState();

그리고 useEffect 부분을 수정해줌

useEffect(() => {
    if (diaryList.length >= 1) {
      const targetDiary = diaryList.find(
        (it) => parseInt(it.id) === parseInt(id)
      );
      console.log(targetDiary);

      if (targetDiary) {
        setOriginData(targetDiary);
      } else {
        navigate("/", { replace: true });
      }
    }
  }, [id, diaryList]);

targetDiarydiaryList에서 id가 같은 파일을 찾아 담는 변수이고,
setOriginDatatargetDiary로 해주는 작업이다.

{originData && <DiaryEditor isEdit={true} originData={originData} />}

그리고 리턴 부분에 추가해주면 된다.

header & 오류 해결

나는 처음에 수정하기랑 작성하기 헤더 부분이 다르게 생겨서
MyHeader 따로 DiaryEditor 따로 만들어서 붙이면 된다고 생각해서 그렇게 했는데,
DiaryEditor에서 Header까지 만들고,
isEdittrue일 경우를 조건으로 해서 바꾸면 되는 거였음!

	<MyHeader
          headText={isEdit ? "일기 수정하기" : "새 일기쓰기"}
          leftChild={
            <MyButton text={"< 뒤로가기"} onClick={() => navigate(-1)} />
          }
          rightChild={
            isEdit && (
             <MyButton
                text={"삭제하기"}
                type={"negative"}
                onClick={handleRemove}
             />
            )
          }
        />

근데 여기까지 했는데 계속 헤더가 안 나오는 것이었따..
알고 봤더니 className이 나는 중간에 대문자가 안들어갔었던것
근데 만들때 당연히 대문자로 중간에 썼겠지 하고 headText,, 등등을 적고
아무리 해봐도 안되는 것이다 ㅠㅠㅠ 결국엔 찾아가지고.. header 설정 완료..



수정 기능

DiaryEditor.js

일단 Edit.js에서 넘겨준 2개의 프롭을 DiaryEditor.js 에서 받아준다.

const DiaryEditor = ({ isEdit, originData }) => {
  	...

useContext를 이용해서 onEdit, onRemove 함수를 가지고 온다.

const { onCreate, onEdit, onRemove } = useContext(DiaryDispatchContext);

그리고 useEffect를 이용해서 isEdit과, originData 프롭이 바뀌면,
현재 isEdit이 true일때, 그러니까 작성하기에서 내려준 게 아니라
수정하기에서 내려주었을 때만 이 로직이 작동하게 함.

  useEffect(() => {
    if (isEdit) {
      setDate(getStringDate(new Date(parseInt(originData.date))));
      setEmotion(originData.emotion);
      setContent(originData.content);
    }
  }, [isEdit, originData]);



그리고 handleSubmit 함수를 조금 수정함. + handleRemove 함수 추가

const handleSubmit = () => {
    if (content.length < 1) {
      contentRef.current.focus();
      return;
    }

    if (
      window.confirm(
        isEdit ? "일기를 수정하시겠습니까?" : "새로운 일기를 작성하시겠습니까?"
      )
    ) {
      if (!isEdit) {
        onCreate(date, content, emotion);
      } else {
        onEdit(originData.id, date, content, emotion);
      }
    }
    navigate("/", { replace: true });
  };


const handleRemove = () => {
    if (window.confirm("정말 삭제하시겠습니까?")) {
      onRemove(originData.id);
      navigate("/", { replace: true });
    }
  };

App.js 에서 onEdit 함수와 onRemove 함수를 보면,

// REMOVE
  const onRemove = (targetId) => {
    dispatch({ type: "REMOVE", targetId });
  };

  // EDIT
  const onEdit = (targetId, date, content, emotion) => {
    dispatch({
      type: "EDIT",
      data: {
        id: targetId,
        date: new Date(date).getTime(),
        content,
        emotion,
      },
    });
  };

이렇게 생겼다.
즉 받아오는 props가 각각 targetId / targetId, date, content, emotion 이기 때문에
originData.idtargetId 자리에 받아온다.

문제 & 해결

이렇게 하면 이제 수정작업 완료! 인데 수정이 왜 안되는건지 ...^^:
계속 찾고 찾다가 결국엔 찾았다 ㅠ_ㅠ
Edit이랑 DiaryEditor만 뚫어지게 째려보다가, 결국 reducer함수의 문제였다는 걸 알았음.

App.js

	case "EDIT": {
      newState = state.map((it) =>
        it.id === action.data.id ? { ...action.data } : it
      );
      break;
    }

reducer 함수의 'EDIT' 케이스를 수정했다.
처음에 break가 없어서, 계속 수정이 돼도 새로고침이 됐던 모양이다.
아직 로컬스토리지나 배포에 담지 않고 임시로만 계속 저장이 되니
새로고침이 되면 리스트가 더미데이터로 새로고침 되는데,
그 과정에서 생겨난 거였나보다.. ㅠ ㅠ 아무튼 이부분을 수정해서 Edit기능(UPDATE)을 완료했다

0개의 댓글