-
[TIL] Class component stateDevelope/React 2020. 5. 12. 12:31
1. state
◎ state는 컴포넌트 내부에서 선언하며 내부에서 값을 변경할 수 있다.
함수형 컴포넌트와 state를 다루는데 방법에 차이가 있어서 기록을 남기자.
2. state의 사용법
◎ 동적인 데이터를 다룰 땐 바로 state를 사용한다.
함수형 컴포넌트에서도 연습했던 카운터 예제를 통해 연습해보자.
CounterClass라는 컴포넌트를 만들고 코드는 다음과 같다.
위의 코드를 한번 살펴보자.
2-1. state 정의
◎ constructor 에서 super(props)를 호출 한 이유는 , 우리가 컴포넌트를 만들게 되면서, Component를 상속했으며, 우리가 이렇게 constructor를 작성하게 되면 기존의 클래스 생성자를 덮어쓰게 된다. 그렇기에 리액트 컴포넌트가 지니고 있던 생성자를 super를 통하여 미리 실행하고, 그다음에 state를 설정해주는 것이다.
2-2. 메소드 작성
◎ 컴포넌트에 메소드는 화살표 함수로 작성하였다.
onIncrease = () => { const { number } = this.state; this.setState({ number: number + 1 }); } onDecrease = () => { const { number } = this.state; this.setState({ number: number - 1 }); }
일반 함수로 작성해도 되지만 나중에 버튼에서 클릭이벤트가 발생했을 때, this가 undefined로 나타나서 제대로 처리되지 않게 된다.
그 이유는 함수가 버튼의 클릭이벤트로 전달이 되는 과정에서 "this"와의 연결이 끊겨버리기 때문이다.
onIncrease() { const { number } = this.state; this.setState = ({ number: number + 1 }) }
일반 함수로 사용했을 때 +버튼을 클릭하면 오류를 보게 될 것이다.
일반 함수로 사용하고 싶을 때는 constructor에서 bind( )를 사용해줘야 한다.
constructor(props) { super(props); this.onIncrease = this.onIncrease.bind(this); }
2-3. setState
◎ state에 있는 값을 바꾸기 위해서는 this.setState를 무조건 거쳐야 한다. 리액트에서는, 이 함수가 호출되면서 컴포넌트가 리렌더링 되도록 설계되어 있다.
처음에 작성했던 코드는 다음과 같다.
this.setState({ number: this.state.number + 1 });
큰 문제는 아니지만, 굳이 또 this.state를 조회해야 한다.
코드는 최대한 간결하게 하는 게 좋다. 우리는 비구조화 할당 문법을 이전에 배웠다.
그래서 기존 코드를 비구조화 할당 문법을 사용하여 다시 고쳤다.
const { number } = this.state; this.setState({ number : number + 1 });
훨씬 더 깔끔해진 코드를 확인할 수 있다.
2-4. 이벤트 설정
◎ render 함수에서 이벤트 설정을 한 부분을 확인해보자.
render() { return ( <> <h1>카운터</h1> <div>값: {this.state.number}</div> <button onClick={this.onIncrease}>+</button> <button onClick={this.onDecrease}>-</button> </> ); }
버튼이 클릭되면 설정한 함수가 각각 호출되도록 설정하였다.
함수를 설정할 때는 주의사항이 있다.
이 주의사항은 함수형 컴포넌트에서도 동일하다.
-
이벤트 이름을 설정할 때 camelCase로 설정해 주어야 한다.
-
이벤트에 전달해주는 값은 함수여야 한다. 만약에 onClick={this.onIncrease()} 식으로 하게 되면 렌더링을 할 때마다 해당 함수가 호출된다.
3. 궁금점 및 문제점 및 해결방법
◎ 버튼을 눌렀을 때 setState 된 number를 확인해보고 싶어 졌다.
지금은 버튼이 두 개밖에 없지만, 나중에 프로젝트를 들어가게 되면 버튼은 무수히 많을 것이고 바뀐 값을 확인해야 하는 경우가 생기기 때문이다.
그래서 내가 생각한 대로 console을 통해 값을 확인해 보았다.
첫 번째 방식은 onIncrease 함수 내에서 this.setState 아래에 콘솔을 찍어보았다.
하지만 결과는 이 전 number값이 나왔다.. 왜지?
두 번째 방식은 render 함수 내에서 콘솔을 찍어보았다.
바뀐 값이 잘 나온다. 하지만 콘솔이 두 번 찍힌다.
그 이유는 this.setState 함수가 호출되면서 컴포넌트가 리렌더링 되도록 설계되어 있기 때문이다.
바뀐 값은 잘 나오지만 렌더링이 두 번 되는 게 맘에 안 든다..
검색 또 검색을 해보았다..
세 번째 방식은 this.setState({})에서 콘솔을 찍는 방법이다.
찾아보니까 this.setState는 비동기 방식으로 작동한다고 한다..(비동기에 대해서는 다음 시간에 정리!!)
하지만 결과는 버튼을 클릭할 때마다 이전 값이 찍히는 결과가 나왔다..
4. 해결방법
◎ 검색해보고 따라 해도 안돼서 결국 멘토님께 질문을 드렸다.
멘토님의 답안은 다음 코드와 같다.
this.setState는 비동기 방식이기 때문에 this.setState에서 함수를 호출하여 console을 찍어야 한다고 말씀해주셨다..
원하는 결과로 console에 잘 나온다.
비동기에 대해서 좀 알아봐야겠다.
5. 느낀 점
◎ 함수형 컴포넌트를 먼저 공부하고 클래스형 컴포넌트를 공부하니까
비슷하지만 차이점이 많은 거 같다.
오히려 더 깔끔한 코드는 함수형 컴포넌트인거 같고, Hoos을 이용해 state값을 동적으로 변화는 것이 더 괜찮은 듯..?
※ 참조
https://www.freecodecamp.org/forum/t/solved-this-setstate-is-updating-state-after-console-log/206985
'Develope > React' 카테고리의 다른 글
[TIL] concat( ) VS push( ) (0) 2020.05.18 [TIL] Class component input 상태 관리 (0) 2020.05.16 [TIL] React Hook 1. useState (0) 2020.05.11 [TIL] Function component props 를 통해 컴포넌트에게 값 전달하기 (0) 2020.05.10 [TIL] Function component, JSX (0) 2020.05.08 -