먼저 현재 일기의 데이터를 가져올 수 있게 해야함.
<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
번호를 바꿔도 다른 일기를 잘 가지고 온다.
...
if (targetDiary) {
} else {
navigate("/", { replace: true });
}
글이 6번까지밖에없는데 /edit/9
를 입력하면
잘못된 입력이기 때문에, 홈으로 돌아가게 만들어주는 코드 추가.
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]);
targetDiary
는 diaryList
에서 id가 같은 파일을 찾아 담는 변수이고,
setOriginData
를 targetDiary
로 해주는 작업이다.
{originData && <DiaryEditor isEdit={true} originData={originData} />}
그리고 리턴 부분에 추가해주면 된다.
나는 처음에 수정하기랑 작성하기 헤더 부분이 다르게 생겨서
MyHeader 따로 DiaryEditor 따로 만들어서 붙이면 된다고 생각해서 그렇게 했는데,
DiaryEditor에서 Header까지 만들고,
isEdit
이 true
일 경우를 조건으로 해서 바꾸면 되는 거였음!
<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.id
를 targetId
자리에 받아온다.
이렇게 하면 이제 수정작업 완료! 인데 수정이 왜 안되는건지 ...^^:
계속 찾고 찾다가 결국엔 찾았다 ㅠ_ㅠ
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)을 완료했다