이어서...
- 리스트 렌더링(조회)
- 데이터 추가
- 데이터 삭제
- 데이터 수정
3. 데이터 삭제
데이터 삭제는 앞서서 했던 데이터 추가와 아주 유사하다!!
우선 DiaryItem에 content 밑 부분에 삭제 버튼을 만들어주자
그다음 onClick 리스너를 달아놓자 id 도 한번 찍어보면 이 일기 아이템의 Id 가 찍힌다이 id로 삭제로직을 짜볼 것이다
<div>
<button onClick={()=>{
console.log(id);
}}>삭제하기</button>
</div>
생각을 해보자 삭제 버튼을 누르면 현재 일기의 아이템이 들어있는 App.js 에 있는 [data, setData]의 data값 중
내가 삭제할 일기를 뺀 나머지 일기들만 새로 만들어줘야 한다
그러므로 우리는 App.js에서 data에 손을 대야 한다 바로 onDelete 함수를 만들어보자
const onDelete= (targetId)=>{
console.log(`${targetId}번의 일기가 삭제되었습니다`)
}
함수만 만들어 두면 뭐 하나 prop으로 넘겨줘야지 그치그치
onDelete함수를 App.js 에서 생성하였으니 이 함수가 필요한 DiaryItem까지 전달하려면
DiaryItem의 부모 컴포넌트인 DiaryIist를 거쳐서 보내야 한다 DiaryIist에는 onDelete함수가 필요하지도 않은데 말이다
이것은 props drilling이라 한다
props drilling ↓
Prop Drilling 은 props를 오로지 하위 컴포넌트로 전달하는 용도로만 쓰이는 컴포넌트들을 거치면서 React Component 트리의 한 부분에서 다른 부분으로 데이터를 전달하는 과정입니다.
솔직히 많아도 문제는 없다 하지만 점점 깊어질수록 해당 props를 추적하기도 어렵고 유지보수에도 매우 좋지 않음!
뭐 어쩔 수 없으니 보내보자
DiaryList에 prop으로 보내주고
DiaryList에선 prop 받아서 다시 DiaryItem으로 보내주고
마침내 필요한 곳까지 왔다
그럼 바로 사용해 보자
<div>
<button onClick={()=>{
if(window.confirm(`${id}번째 일기를 삭제하시겠습니까?`)){
onDelete(id);
}
}}>삭제하기</button>
</div>
버튼을 눌렀을 때 확인창이 뜨게 해 주고 그다음 onDelete함수에 해당 일기의 id를 인자로 보내준다
그럼 onDelete에서 받아보자
여기선 js의 배열내장함수 중 하나인 filter를 사용해 해당 번호를 제외한 배열을 다시 생성해볼 것이다
const onDelete = (targetId)=>{
console.log(`${targetId}가 삭제되었습니다`);
const newDiaryList= data.filter((it)=>it.id!==targetId);
setData(newDiaryList);
}
현재 data배열에 filter을 하여 해당 id와 같지 않은 배열들만 새로운 배열에 담아서
setData함수에 넘겨줬다
잘 삭제되는 걸 볼 수 있다 ㅎㅎ
4. 데이터 수정
마지막 데이터 수정을 해보자
로직을 생각해 보자면 이 수정은 삭제와 마찬가지로 DiaryItem에서 일어나야 할 것이다! 이미 써진 일기를 수정해야 하는 것이기
때문에 그러므로 삭제버튼 옆에 수정버튼 하나 만들어주자뭐 위의 방법과 같으므로 따로 설명은 안 하겠다!
버튼을 생성하였다!
그럼 수정하기 버튼을 클릭하면 어떤 상황이 일어나야 할까?
ㅇㅇㅇㅇㅇ라고 써진 본문대신에 새로운 일기를 수정할 수 있는 폼이 나와야 할 것이다!
이것을 다루기 위해 새로운 state를 생성해 보자
const [isEdit,setIsEdit]=useState(false);
boolean값을 주고 true일 때 수정 중인 것이다
그리고 이것을 껐다 켜줄 toggle함수도 만들어보자
const toggleIsEdit=()=>setIsEdit(!isEdit);
현재상태에 not연산자를 사용해 상태를 반전시켜 준다
그리고 이것을 수정하기 버튼이 눌리면 실행되게 onClick이벤트를 이용해 달아 준다
그럼 수정 중일 때와 아닐 때 바뀌어야 할 부분은? 바로 content부분이다
이<div> 부분을 수정해 보자
<div className="content">
{isEdit?<>
<textarea/>
</>:<>{content}</>}
</div>
삼항연산자를 사용해 수정 중일 때의 렌더링 할 요소 우선 textarea 넣어주고, 아닐때의 렌더링할 요소를 넣어준다 아닐 때는 기존의 값이므로 {content} 그대로 넣어주자
그럼 수정하기 버튼을 누르면 새로운 textarea가 생기는 걸 볼 수 있다
이 수정할 때의 textarea에 쓰는 글들도 state를 사용해 다뤄보자
const [localContent,setLocalContent] = useState(content);
초기값을 빈 문자열이 아니라 현재의 content를 주는 이유는
보통 글 수정을 할때 기존의 글에서 수정을 시작하기 때문!
그 후 맨 처음 다뤘던 사용자 입력처리에서 했던 거처럼 태그에 value를 넣어주고 onChange를 이용해 조작해 보자
<textarea value={localContent} onChange={(e)=>setLocalContent(e.target.value)}/>
오케이
그럼 content부분만 바뀌어야 할까?
아니다 수정하기 버튼을 눌렀을 때 버튼들의 상태도 바꿔줘야 한다
<div>
{isEdit?<><button>수정 취소</button>
<button>수정 완료</button></>:
<><button onClick={handelDelete}>삭제하기</button>
<button onClick={toggleIsEdit}>수정하기</button></>}
</div>
위와 같은 삼항조건식을 이용해 수정 중이라면 수정취소와 수정완료 버튼을 아니라면 그대로 둔다
여기서 한 가지 문제가 발생한다
수정하기를 눌러서 수정을 한 후 수정취소를 누르고 다시 수정하기를 누르면 이전의 값이 그대로 남아있다
수정 부분의 textarea의 상태변화함수인 setLocalContent를 초기화를 안 해줬기 때문이다
//수정상태에서 나간다
const handleQuitEdit = ()=>{
setIsEdit(false);
setLocalContent(content);
}
수정취소를 누르면 발생할 핸들러를 하나 만들어주자
수정상태를 수정 중이 아님으로 바꿔 주로 setLocalContent에 기존의 content를 넣어주면 된다
수정취소 버튼에 달아주자 이건 이제 할 수 있지요?
이제 남은 건 수정완료 버튼을 눌렀을 때 localContent의 값이 setData의 content값으로 변경되면 된다!
그럼 다시 App.js까지 올라가 수정하는 함수를 만들어주자
const onEdit = (targetId,newContent)=>{
setData(
data.map((it)=>it.id===targetId?{...it,content:newContent}:it)
)
}
매개변수로는 targetId와 수정할 newContent를 받아오고
data.map을 하여 수정할 아이디가 맞으면 우선 그 일기를 스프레드 연산자로 다 가져온 다음에
content부분만 newContent로 업데이트해주면 된다!
아까 했듯이 prop으로 DiaryItem까지 넘겨준다
이것이 조작해 보자
const handleEdit = ()=>{
if(localContent.length<5){
localContentInput.current.focus();
return;
}
if(window.confirm(`${id}번째 일기를 수정하시겠습니까?`)){
onEdit(id,localContent);
toggleIsEdit();
}
}
처음 사용자 입력에서 했듯이 본문의 길이가 5가 넘어가지 않으면 useRef를 사용해 focus를 준다
(줘야 할 부분은 바로 textarea!!)
다음 안내창을 띄우고 onEdit함수를 호출한 후 수정상태를 바꿔주면 끝!
이 함수도 그랬듯이 수정완료 버튼에 달아주면 됩니다!!
잘 돌아가용!
..💬
리액트는 데이터 흐름이 단방향이고 이벤트는 아래서 위로 데이터는 위에서 아래로
이러한 특성 때문에 props drilling이 발생할 수 있음!
3번에 나눠서 데이터 조작하는 법을 알아봤다! 확실히 state ref prop 다루는 게 익숙해졌다
더 힘내잣!
'개발🐕 > React' 카테고리의 다른 글
[React Project: 간단한 일기장(6)] 최적화1 - useMemo (0) | 2023.01.05 |
---|---|
[React] 리액트 useEffect? feat. Lifecycle (+예제코드) (1) | 2023.01.04 |
[React Project: 간단한 일기장(4)] 배열사용해서 데이터 조작하기2- 데이터 추가 (1) | 2023.01.03 |
[React Project: 간단한 일기장(3)] 배열사용해서 데이터 조작하기1- 리스트 렌더링 (0) | 2023.01.03 |
[React Project: 간단한 일기장(2)] DOM 조작하기 - useRef (0) | 2023.01.02 |