☑️ UPDATE
// src/App.js
const onRemove = (targetId) => {
console.log(`${targetId}가 삭제되었습니다`);
const newDiaryList = data.filter((it) => it.id !== targetId);
//console.log(newDiaryList);
setData(newDiaryList);
};
<DiaryList onRemove={onRemove} diaryList={date} />
// src/DiaryList.js
const DiaryList = ({ onEdit, onRemove, diaryList }) => {
return (
<div className="DiaryList">
<h2>일기 리스트</h2>
<h4>{diaryList.length}개의 일기가 있습니다.</h4>
<div>
{diaryList.map((it) => (
<DiaryItem key={it.id} {...it} onEdit={onEdit} onRemove={onRemove} />
))}
</div>
</div>
);
};
// src/DiaryItem.js
const DiaryItem = ({
onRemove, id, author, content, emotion, created_date }) => {
☑️ 수정 기능 버튼 만들기
☑️ handleRemove 함수 생성
☑️ 수정하기 상태 추가
const [isEdit, setIsEdit] = useState(false);
const toggleIsEdit = () => setIsEdit(!isEdit);
☑️ 수정하기 버튼 클릭 시 수정 폼 생성하기 추가
☑️ 수정 폼 관리 - state로 핸들링하기
const [localContent, setLocalContent] = useState();
const localContentInput = useRef();
<div className="content">
{isEdit
? <><textarea ref={localContentInput}
value={localContent}
onChange={(e) => setLocalContent(e.target.value)} /></>
: <>{content}</>
}
</div>
☑️ 수정하기 버튼 클릭 시 수정취소/수정완료 버튼으로 렌더링
{isEdit
? <>
<button onClick={handleQuitEdit}>수정 취소</button>
<button onClick={handleEdit}>수정 완료</button>
</>
: <>
<button onClick={handleRemove}>삭제하기</button>
<button onClick={toggleIsEdit}>수정하기</button>
</>
}
☑️ 수정 폼이 나타났을 때 원본 데이터가 들어오도록 기능 추가
const [localContent, setLocalContent] = useState(content);
☑️ 수정 폼 초기화 적용
const handleQuitEdit = () => {
setIsEdit(false); // false
setLocalContent(content); // 원래대로
};
☑️ 일기 아이템이 진짜 수정되서 저장되도록 적용
수정 완료 이벤트는 DiaryItem 컴포넌트에서 App 컴포넌트로 가야함
Data를 가지고 있는 App 컴포넌트에 수정하는 기능을 넣고, DiaryItem 컴포넌트로 보내주기
src/App.js
// 어떤 id를 가진 일기를 수정할 것인지(targetId) 수정된 데이터가 뭔지(newContent)
// onEdit 특정 일기 데이터를 수정하는 함수
const onEdit = (targetId, newContent) => {
// setData를 통해서 어떤 값을 전달한다
setData(
// 변경 시키는 값 만들기
// 원본데이터에 map 내장함수 사용
// 모든 요소(it)을 순회한 후 새로운 배열을 만들어서 setData에 저장
// 새로운 배열은? 수정이 완료된 배열을 전달해야 한다
data.map( (it) =>
// 수정대상이라면?
it.id === targetId
// 컨텐츠가 뉴컨텐츠로 바뀜(수정된 배열)로 교체해줄 것인지
? { ...it, content: newContent }
// 수정대상이 아니면 원래있던 배열을 다시 반환할 것인지 (원본값)
: it
)
);
};
☑️ onEdit 함수 DiaryList 컴포넌트에 전달
src/App.js
return (
<div className="App">
<DiaryEditor onCreate={onCreate} />
<DiaryList onEdit={onEdit} onRemove={onRemove} diaryList={data} />
</div>
);
☑️ DiaryList 컴포넌트는 Prop으로 전달
src/DiaryList.js
const DiaryList = ({ onEdit, onRemove, diaryList }) => {
return (
<div className="DiaryList">
<h2>일기 리스트</h2>
<h4>{diaryList.length}개의 일기가 있습니다.</h4>
<div>
{diaryList.map((it) => (
<DiaryItem key={it.id} {...it} onEdit={onEdit} onRemove={onRemove} />
))}
</div>
</div>
);
};
☑️ DiaryItem 컴포넌트는 DiaryList를 통해 전달받기
src/DiaryItem.js
import { useRef, useState } from "react";
const DiaryItem = ({
onEdit, onRemove, id, author, content, emotion, created_date
}) => {
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) {
localContentInput.current.focus();
return;
}
if(window.confirm(`${id}번 째 일기를 수정하시겠습니까?`)){
onEdit(id, localContent);
toggleIsEdit();
}
};
return (
<div className="DiaryItem">
<div className="info">
<span className="author_info">
| 작성자 : {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)} /></>
: <>{content}</>
}
</div>
{/* 삭제하기/수정하기 버튼 추가 */}
{isEdit
? <>
<button onClick={handleQuitEdit}>수정 취소</button>
<button onClick={handleEdit}>수정 완료</button>
</>
: <>
<button onClick={handleRemove}>삭제하기</button>
<button onClick={toggleIsEdit}>수정하기</button>
</>
}
</div>
);
};
export default DiaryItem;
컴포넌트 설계 구조와 데이터 전달 흐름
출처 - https://velopert.com/3528
출처 - https://velog.io/@youthfulhps/What-is-Redux-and-why-use-it
복잡성
출처 - 생활코딩
💬 작업하다가 결국엔... sourcetree
를 설치했다.
예전에 다녔던 회사에서 전임자분이 알려주셨던 그 환경설정이 아직도 익숙하다는 게(흠)
CLI에 익숙해져야 하는데 아직은 GUI가 더 익숙한 나
(사고전환중🙃)