[React] 리액트에서 데이터 수정하기
🔮 이전 강의 backup
수정 사항
- onDelete -> onRemove
- onClick 화살표 함수 가독성 떨어짐 -> 구현부를 따로 빼서 handleRemove 함수 구현
// DiaryItem.js
const DiaryItem = ({
onRemove,
author,
content,
created_date,
emotion,
id,
}) => {
const handleRemove = () => {
if (window.confirm(`${id}번 째 일기를 삭제하시겠습니까?`)) {
onRemove(id);
}
};
return (
<div className="DiaryItem">
<div className="info">
<span>
작성자 : {author} | 감정점수 : {emotion}
</span>
<br />
<span className="date"> {new Date(created_date).toLocaleString()}</span>
</div>
<div className="content">{content}</div>
<button onClick={handleRemove}>삭제하기</button>
<button>수정하기</button>
</div>
);
};
export default DiaryItem;
📐 수정하기 버튼 만들기
📍 버튼 클릭하면 작동해야되는 기능
- 버튼 클릭 ->
<button>수정하기</button>
- 리스트 내에서 수정 폼 생성 -> state로 생성
📍 수정폼 만들기 step 1.
import { useState } from "react";
const DiaryItem = ({
onRemove,
author,
content,
created_date,
emotion,
id,
}) => {
const [isEdit, setIsEdit] = useState(false); // 🌟
const toggleIsEdit = () => setIsEdit(!isEdit); // 🌟
const handleRemove = () => {
if (window.confirm(`${id}번 째 일기를 삭제하시겠습니까?`)) {
onRemove(id);
}
};
return (
<div className="DiaryItem">
<div className="info">
<span>
작성자 : {author} | 감정점수 : {emotion}
</span>
<br />
<span className="date"> {new Date(created_date).toLocaleString()}</span>
</div>
<div className="content">{content}</div>
<button onClick={handleRemove}>삭제하기</button>
<button onClick={toggleIsEdit}>수정하기</button>
</div>
);
};
export default DiaryItem;
- isEdit : 현재 수정중이면 true, 아니라면 false를 setState에서 반환받음
- toggleIsEdit : 호출이 되는 순간 원래의 isEdit값을 반전시킨다.
📍 수정폼 만들기 step 2.
toggleIsEdit이 클릭되었을 때 어떻게 구현?
- isEdit === true : 입력창
- isEdit === false : 저장
<div className="content">
{isEdit ? (
<>
<textarea
value={localContent}
onChange={(e) => {
setLocalContent(e.target.value);
}}
/>
</>
) : (
<>{content}</>
)}
</div>
- isEdit === true 라면 입력창(textarea)를 띄운다. -> 수정한 값을 저장하기 위해서는 어떻게,,?
- sol. content 입력했던 방식과 동일하게, 입력받은 값을 localContent로 받아와서 setLocalContent를 통해서 리랜더링한다.
📐 수정 취소, 수정 완료 버튼
📍 수정 취소, 완료 버튼 기본 틀
isEdit에 따라 true이면 수정 취소, 수정 완료 버튼을
isEdit이 false이면 삭제하기, 수정하기 버튼을 구현
📍 수정 취소, 완료 버튼 구현
-
삭제하기, 수정하기는 기존에 구현해놓았던 것이다.
<button onClick={handleRemove}>삭제하기</button> <button onClick={toggleIsEdit}>수정하기</button>
-
수정 취소 버튼 구현
기존에 isEdit이 true니까 textarea가 떴을텐데, 취소를 눌러주었으므로 isEdit을 false로 만들면 된다<button onClick={toggleIsEdit}>수정 취소</button>
❗ 문제점 ❗
근데 여기서 수정하기 버튼을 눌러 입력을 수정 취소 를 누르고 다시 수정하기 버튼을 누르면 기존에 수정하다가 취소한 내용이 그대로 있다.
💡 해결책 💡
기존의 content를 setLocalContent()를 통해서 기존 내용이 다시 textarea에 입력되도록 한다.const handleQuitEdit = () => { setIsEdit(false); setLocalContent(content); }; <button onClick={handleQuitEdit}>수정 취소</button>;
- setLocalContent : 수정한 내용을 저장하기 위해 만들어놓은 함수
이 함수를 이용하여 수정 전 내용이 들어있는 content를 넣어준다.
- setLocalContent : 수정한 내용을 저장하기 위해 만들어놓은 함수
-
수정 완료 버튼 구현
생각을 해보았을 때, 지금 App.js에서는 데이터를 다루고 있다.
그렇기 때문에 데이터를 수정하기 위해서는 App.js까지 몇 번째 값이 어떤 내용으로 변경이 되어야 되는지 전달을 해주어야 되고(DiaryItem.js -> App.js : Event), App.js에서는 수정을 위한 함수를 구현하여 DiaryList를 거쳐 DiaryItem까지 와서(App.js -> DiaryList.js -> DiaryItem.js : data) 내용을 수정한 것을 출력해준다. .- App.js 수정
const onEdit = (targetId, newContent) => { setData( data.map((it) => it.id === targetId ? { ...it, content: newContent } : it ) ); }; <DiaryList onEdit={onEdit} diaryList={data} onRemove={onRemove} />;
수정될 위치를 targetId, 수정된 내용을 newContent로 DiaryItem에서 가져왔다.
그럼 얘 어떻게 수정해? -> 앞에서 객체별로 데이터를 넣어주기 위해서 setData()를 통해서 일기 리스트 객체에 값을 추가하거나 삭제했다. 수정도 마찬가지로 setData()를 쓰는데, 수정할 ID의 객체의 content만 newContent로 수정
-
DiaryItem.js 수정
const handleEdit = () => { if (localContent.length < 5) { localContentInput.current.focus(); return; } if (window.confirm(`${id}번 째 일기를 수정하시겠습니까?`)) { onEdit(id, localContent); toggleIsEdit(); } };
🌗 결과
댓글남기기