HYEWON JUNG의 개발일지
20231115 TIL Fan Letter -3 상세페이지 수정 삭제 구현 본문
목표
- styled component 적용
- detail 수정 삭제 구현
- 이미지 디폴트 넣기
- drilling 리팩토링 후 context 넘어가기
새로 알게 된것/ 오늘의 코드
상세페이지 버튼 기능 구현
1번째 삽질
<li style={fanLetterStyle} key={letter.id} onClick={()=>{navigate(`/${letter.id}`) {state:letters}}}>
navigate로 data 내려주기
const {state} = useLocation()
Detail에서 data 받기
const [detail, setDetail] =useState(state)
const removeLetterBtnEvent = (id) => {
const filteredLetter = letters.filter(to => to.id !== id)
setDetail(filteredLetter)
}
새롭게 state를 준 후 초기값에 navigate로 받아온 letters(state)를 넣어줬다. 그리고 삭제 기능 넣고 실행을 하면 아무것도 바뀌지 않는다.
console.log(filteredLetter)를 해보면 datail의 데이터에서 삭제되는 것을 볼 수 있었다.
안되는 이유는 조금만 생각해도 알 수 있었다.
state를 새로 선언하고 그 state를 set해준 것이기 때문에 Letters에 있는 letters state에는 아무런 변화가 생기지 않는 것은 당연하다.
2번째 삽질 (성공)
<li style={fanLetterStyle} key={letter.id} onClick={()=>{navigate(`/${letter.id}`) {state:letters} {setLetters: setLetters}}}>
안 될 것은 예상했지만 마지막 발악으로 해봤다.
setLetter is not a function 에러가 뜬다. setLetter는 안끌어와졌다.
타이밍 좋게 튜터님과 면담이 생겨서 여쭤봤다.
튜터님 :"가장 상위 컴포넌트인 App에서 state를 선언하고 내려주는 것은 어떨까요?"
나: '와 천재신가..? 아님 내가 멍청인가?'
Detail보다 상위요소에서 props drilling이 시작되면 Detail에서 받을 수 있는 것이 당연한데 왜 생각을 못했을 까?
이실직고하면 너무 멍청하게도
이렇게 Detail의 상위 요소가 없다고 생각해버렸다.. 와우.. 완전히 이해를 잘못하고 있던 상태였던 것이다. 지금 생각하면 너무 바보같이 생각한 것 같다.
Router 에서 Home을 옮겨지는 Route로직을 잘 이해했더라면 이런 일이 생기지 않았을 텐데..
아무튼 이제라도 이해하고 넘어가서 다행이다!
이렇게 drilling을 수정해주고 삭제 버튼을 구현 했더니 !
const removeLetterBtnEvent = (id) => {
const filteredLetter = letters.filter(to => to.id !== id)
setLetters(filteredLetter)
}
오류 빠밤!
이건 조금 곰곰히 생각해보면 문제점을 알 수 있다.
버튼을 눌렀을 때 삭제되면서 일어나는 과정을 보면
1. 버튼을 누른다
2. 필터된 값이 나오면서 해당 데이터가 사라진다.
3. 우리는 아직 그 id의 detailpage에 있다.
4. 그 id의 data는 사라졌기에 읽힐 것이 없다.
이렇기에 그 페이지에 머물러 있으면 오류가 나는 것은 당연하다. 버튼을 클릭하면 다시 Home으로 가는 로직도 포함되어야한다.
const navigate = useNavigate()
const removeLetterBtnEvent = (id) => {
if(window.confirm("정말로 지우시겠습니까?")){
const filteredLetter = letters.filter(to => to.id !== id)
setLetters(filteredLetter)
navigate(`/`)
}else{
alert("취소되었습니다")
}
}
하는 겸에 확인 절차로 추가했다.
삭제가 잘 이루어지는 것을 볼 수 있었다.! 어제 하루종일 이것때문에 진도를 못나갔는데 사실은 1시간만에 끝낼 수 있었다니.. 코드를 넓게 보는 사고가 필요하다!!
수정기능 구현하기
완성본을 미리 보자면.
수정 버튼을 누르면 p태그가 textarea로 바뀌면서 입력할 수 있게 변경이 된다. 그 후 textarea에서 입력한 값이 p태그에 반영이 될 수 있게 되야한다.
그래서 state 가 2개가 추가로 필요하다!
const [isEdit, setIsEdit] = useState(false)
const [editLetter, setEditLetter] = useState(foundLetter.content)
isEdit은 수정상태인지 아닌지 에 따라 textarea인지p태그 인지 구분해야하니 필요하고 editLetter는 textarea에서 수정한 것을 반영하기 위해서 필요하다!
isEdit상태에 따라 달라지는 것은 두개가 있는데 위에서 말했듯 textarea 랑p태그 , 버튼이 수정중일 땐 수정완료버튼이 뜨고 아닐땐 수정, 삭제가 뜨게 하는 것이다.
우선 textarea , p부터
const editTextHandler = (event) => { setEditLetter(event.target.value) }
{
isEdit ?
<textarea value={editLetter} onChange={editTextHandler}>{foundLetter.content}</textarea> :
<p>{foundLetter.content}</p>
}
textarea에 input이랑 똑같이 value와 onChange를 넣어주면 된다. 삼항 연산자로 isEdit의 상태가 true일경우 textarea를 false일 결우 p를 나타내게 하고 내용은 동일하게 들어가면된다.
그리고 버튼의 경우 동일한 방법인데
{isEdit ? <button onClick={() => (finishEditHandler(foundLetter.id))}>수정완료</button> : <div>
<button onClick={() => { setIsEdit(!isEdit) }}>수정</button>
<button onClick={() => (removeLetterHandler(foundLetter.id))}>삭제</button>
</div>}
수정완료 버튼의 기능은
const finishEditHandler = (id) => {
const editcontent = letters.map((item) => ({
...item, content: item.id === id ? editLetter : item.content
}))
if (editLetter === foundLetter.content) {
alert("수정된 부분이 없습니다.")
} else {
setLetters(editcontent)
setIsEdit(false)
}
}
map돌려서 id체크하고 맞으면 content 부분에 수정된 내용이 들어가고 id가 다른 것들은 그대로 각자의 content를 가진다.
만약 수정된 글과 이전글이 동일 할 경우 alert를 띄우고 아니면 setLetters를 편집된 레터로 넣어주고 isEdit상태로 false로 만들어주면 된다.
목표 달성여부
- styled component 적용
detail 수정 삭제 구현- 이미지 디폴트 넣기
- drilling 리팩토링 후 context 넘어가기
내일 목표
- styled component 적용
- 이미지 디폴트 넣기
- drilling 리팩토링 후 context 넘어가기
'개발일지' 카테고리의 다른 글
20231117-19 WIL 페이지 보수 , redux (2) | 2023.11.20 |
---|---|
20231116 TIL Fan Letter -4 버튼클릭 시 색 변경, 이미지 디폴트 지정, useContext 이용하기 (0) | 2023.11.17 |
20231114 TIL (0) | 2023.11.15 |
20231113 TIL Fan Letter -2 편지추가하기 , 분류버튼, 상세페이지 만들기, router로 연결하기 (1) | 2023.11.14 |
20231107 TIL (0) | 2023.11.11 |