*Udemy의 "React - The Complete Guide" 강의에서 학습한 내용을 정리한 포스팅입니다.
*자바스크립트와 리액트를 배우는 단계라 오류가 있을 수 있습니다. 틀린 내용은 댓글로 말씀해주시면 수정하겠습니다. 감사합니다. :)
1. state 객체는 reference type!
DOM에서 P 태그가 있는 부분을 클릭했을 때 해당 데이터가 DOM에서 사라지도록 해보자. App.js 파일에 deletePersonHandler 메소드를 추가한다.
deletePersonHandler = (personIndex) => {
const persons = this.state.persons;
persons.splice(personIndex, 1);
this.setState({persons: persons});
}
그리고 Person 컴포넌트에 이 메소드를 넘겨주어서 클릭이 일어나면 state를 변경시키므로 DOM에서 사라지게 된다.
{this.state.persons.map((person, index) => {
return <Person
click={() => this.deletePersonHandler(index)}
name={person.name}
age={person.age} />
})}
위처럼 Person 컴포넌트의 click 프로퍼티의 값으로 콜백함수를 통해 deletePersonHandler 메소드를 넘겨주었다. 그런데 여기서 deletePersonHandler 메소드 안에는 큰 문제가 있다. 그게 무엇일까?
자바스크립트에서 객체는 Reference Type이다. 따라서 persons 변수에 현재 담겨있는 값은 this.state.persons가 저장되어 있는 메모리 공간의 주솟값이다. 그런데 이 주솟값에 persons.splice(personIndex, 1)을 할 경우 문제가 발생한다. splice는 원본이 변경되는 mutable한 메소드이다. 따라서 persons.splice는 메모리 주솟값에 저장되어 있는 원본 값에 변형을 가하므로, 이미 this.setState 메소드가 실행되기 이전에 중요한 데이터인 state 데이터에 변형을 가하게 되는 것이다.
# 해결책
deletePersonHandler = (personIndex) => {
const persons = this.state.persons.slice();
// const persons = [...this.state.persons]; 이 방법도 가능하다.
persons.splice(personIndex, 1);
this.setState({persons: persons});
}
따라서 위 코드처럼 변수에 this.state의 값을 담아놓을 경우 원본을 그대로 카피한 후 다뤄줘야 한다. 위 코드는 slice를 통해서 this.state.persons의 값을 그대로 복사하고 있다. 주석처리한 부분은 전개 구문(spread operator)를 통해서 값을 복사한 것이다. 둘 중 어떤 방식을 취해도 상관없고 다만 원본이 변형되지 않도록 반드시 값을 복사한 후 사용해야 한다는 점에 주의하자!
'Javascript 공부 > React' 카테고리의 다른 글
리액트의 생명 주기(LifeCycle) 메소드 (0) | 2019.12.12 |
---|---|
비동기로 작동하는 setState 이해하기 (0) | 2019.12.11 |
React에서 조건문 사용하기 (0) | 2019.12.10 |
리액트 useState() Hook : 함수형 컴포넌트로 state 관리하기 (0) | 2019.12.05 |
리액트 실습 2 - Monsters Rolodex (0) | 2019.11.29 |
댓글