저번시간에 추가한 onDelete 함수의 이름을 onRemove로 변환시켰다.
그리고 수정버튼을 입력해주기전에
지난시간에 만들었던 버튼 속 onClick 이벤트 함수를 가독성을 위해
따로 변수에 저장해주었다.
const handleRemove = () => {
if (window.confirm(`${id}번째 일기를 정말 삭제하시겠습니까?`)) {
onRemove(id);
};
}
<button onClick={handleRemove}> 삭제하기 </button>
그리고 수정하기 버튼을 만들어주었다.
이제 수정하기를 누르면 수정할 수 있는 폼이 내용안에 뜨도록 만들어 줄거다.
수정하기
import { useState } from "react";
상태 변화를 위해 useState를 불러주고
const [isEdit, setIsEdt] = useState(false);
state를 만들어준다.
수정중인지 아닌지 확인 할 true, false boolean 값을 줄 것이다.
만약 true 일 경우
이 JSX에서 수정중으로 간주해서 코드를 작성하도록 할 것이다 .
const togleIsEdit = () => setIsEdit(!isEdit);
호출이 되는 순간 원래 isEdit이 가지고 있던 값을 !(not)연산을 통해서 반전연산을 하게된다. (togle 발생)
<button onClick={togleIsEdit}> 수정하기 </button>
토글버튼을 수정하기 버튼을 누르면
isEdit 값이 true > false로 또는 false > true로 변하게 된다
기존에 내용이 뜨던 div를 수정해줄 것이다
<div className="content">
{isEdit ? <><textarea></textarea></> : <>{content}</>}
</div>
{content}만 있던곳에 삼항연산자를 넣어
isEdit (수정중상태) 가 true면 textarea 태그를, false면 내용을 보여준다.
이제 수정하기 버튼을 누르면 수정폼이 뜬다
const [localContent, setLocalContent] = useState("content");
이전에 create처럼 textarea 값을 넣을 수 있도록 할것이다.
useState에 content를 넣어서 수정을 눌러도 이전에 작성한 글이 보이게 했다.
<div className="content">
{isEdit ? (
<>
<textarea>
value={localContent}
onChange={(e) => { setLocalContent(e.target.value) }}
</textarea>
</>
) : (
<>{content}</>
)}
</div>
localContent에 매핑시켜서 값이 수정될 수 있게 하고,
수정 시 수정버튼 폼도 바뀔 수 있도록 해보자
const handleQuitEdit = () => {
setIsEdit(false);
setLocalContent(content);
}
수정
const onEdit = (targetId, newContent) => {
setData(
data.map((it) => it.id === targetId ? { ...it, content: newContent } : it)
)
}
수정 완료 버튼 동작을 위해 App.js가서 수정하는 함수를 만들어준다.
원본데이터 배열에 Map 내장함수를 이용해 모든 요소를 순회하며 새로운 배열(수정된 배열)을 만들어 setData로 전달한다
it.id랑 targetId 가 true면 content를 newContent로 바꾸고 아닌 내용들은 그대로 남아있다.
이제 onEdit 함수를 프롭스 드릴링을 통해 DiaryItem까지 전달해준다.
<button onClick={handleEdit} > 수정 완료 </button>
버튼 onClick이벤트에 handleEdit 함수를 넣어주고
const localContentInput = useRef();
useRef를 import하고 localContentInput 레퍼런스 객체를 만들어 준다.
만들어진 localContentInput을 focus가 필요한 textarea에 ref로 매핑해준다
const handleEdit = () => {
if (localContent.length < 5) {
alert("5자 이상 입력하세요");
localContentInput.current.focus();
return;
}
if (window.confirm(`${id}번 째 일기를 수정하시겠습니까?`)) {
onEdit(id, localContent);
toggleIsEdit();
}
onEdit(id, localContent);
}
기존 컨텐츠가 5자이상 입력을 했어야하기때문에 5글자 미만이면 알람과, focus를 해준다.
그리고 수정하기 전 물어보는 프롬포트 창을 .confirm을 사용해 물어보도록 한다.
import { useRef, useState } from "react";
const DiaryItem = ({
onEdit, onRemove, author, content, created_date, emotion, id
}) => {
const [isEdit, setIsEdit] = useState(false);
const toggleIsEdit = () => setIsEdit(!isEdit);
const [localContent, setLocalContent] = useState(content);
const localContentInput = useRef();
const handleRemove = () => {
if (window.confirm(`${id}번째 일기를 정말 삭제하시겠습니까?`)) {
onRemove(id);
};
}
const handleQuitEdit = () => {
setIsEdit(false);
setLocalContent(content);
}
const handleEdit = () => {
if (localContent.length < 5) {
alert("5자 이상 입력하세요");
localContentInput.current.focus();
return;
}
if (window.confirm(`${id}번 째 일기를 수정하시겠습니까?`)) {
onEdit(id, localContent);
toggleIsEdit();
}
onEdit(id, localContent);
}
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">
{isEdit ? (
<>
<textarea
ref={localContentInput}
value={localContent}
onChange={(e) => { setLocalContent(e.target.value) }}>
</textarea>
</>
) : (
<>{content}</>
)}
</div>
{isEdit ? (<>
<button onClick={handleQuitEdit}> 수정 취소 </button>
<button onClick={handleEdit} > 수정 완료 </button>
</>) : (
<>
<button onClick={toggleIsEdit}> 수정하기 </button>
<button onClick={handleRemove}> 삭제하기 </button>
</>
)}
</div>
);
};
export default DiaryItem;
'개발 > Javascript' 카테고리의 다른 글
[React] API 호출하기 (0) | 2022.07.09 |
---|---|
[React] 라이프사이클 제어하기 (0) | 2022.07.08 |
[React] 일기장에 추가한 배열 데이터 삭제하기 ; 프롭스 드릴링? (0) | 2022.07.06 |
[React] 더미데이터가 아닌 내가 작성하고 등록한 일기장 내용으로 List 출력하기 (0) | 2022.07.05 |
[React] 일기장 내용을 List형태로 랜더링한 후 개별 컴포넌트로 만들기 (0) | 2022.07.04 |