ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [TIL] Class component state
    Develope/React 2020. 5. 12. 12:31

    React logo

    1. state

    state는 컴포넌트 내부에서 선언하며 내부에서 값을 변경할 수 있다.

    함수형 컴포넌트와 state를 다루는데 방법에 차이가 있어서 기록을 남기자.

    2. state의 사용법

    ◎ 동적인 데이터를 다룰 땐 바로 state를 사용한다.

    함수형 컴포넌트에서도 연습했던 카운터 예제를 통해 연습해보자.

    CounterClass라는 컴포넌트를 만들고 코드는 다음과 같다.

     

    CounterClass.js

    위의 코드를 한번 살펴보자.

     

    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
     })
    }

    일반 함수로 사용했을 때 +버튼을 클릭하면 오류를 보게 될 것이다.

     

    browser

    일반 함수로 사용하고 싶을 때는 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을 통해 값을 확인해 보았다.

     

    CounterClass.js

    첫 번째 방식은 onIncrease 함수 내에서 this.setState 아래에 콘솔을 찍어보았다.

     

    browser

    하지만 결과는 이 전 number값이 나왔다.. 왜지?

    두 번째 방식은 render 함수 내에서 콘솔을 찍어보았다.

     

    CounterClass.js 
    browser

    바뀐 값이 잘 나온다. 하지만 콘솔이 두 번 찍힌다.

    그 이유는 this.setState 함수가 호출되면서 컴포넌트가 리렌더링 되도록 설계되어 있기 때문이다.

    바뀐 값은 잘 나오지만 렌더링이 두 번 되는 게 맘에 안 든다..

    검색 또 검색을 해보았다..

    세 번째 방식은 this.setState({})에서 콘솔을 찍는 방법이다.

    찾아보니까 this.setState는 비동기 방식으로 작동한다고 한다..(비동기에 대해서는 다음 시간에 정리!!)

     

    CounterClass.js

     하지만 결과는 버튼을 클릭할 때마다 이전 값이 찍히는 결과가 나왔다..

    4. 해결방법

    ◎ 검색해보고 따라 해도 안돼서 결국 멘토님께 질문을 드렸다.

    멘토님의 답안은 다음 코드와 같다.

     

    this.setState는 비동기 방식이기 때문에 this.setState에서 함수를 호출하여 console을 찍어야 한다고 말씀해주셨다..

    원하는 결과로 console에 잘 나온다.

    비동기에 대해서 좀 알아봐야겠다.

    5. 느낀 점

    ◎ 함수형 컴포넌트를 먼저 공부하고 클래스형 컴포넌트를 공부하니까

    비슷하지만 차이점이 많은 거 같다.

    오히려 더 깔끔한 코드는 함수형 컴포넌트인거 같고, Hoos을 이용해 state값을 동적으로 변화는 것이 더 괜찮은 듯..?

    ※ 참조

    https://velopert.com/3629

     

    누구든지 하는 리액트 4편: props 와 state | VELOPERT.LOG

    이 튜토리얼은 10편으로 이뤄진 시리즈입니다. 이전 / 다음 편을 확인하시려면 목차를 확인하세요. 리액트 컴포넌트에서 다루는 데이터는 두개로 나뉩니다. 바로 props 와 state 인데요, 미리 요약�

    velopert.com

    https://www.freecodecamp.org/forum/t/solved-this-setstate-is-updating-state-after-console-log/206985

     

    [SOLVED]this.setState is updating state after console.log

    Hello again everyone, I am building a rock-paper-scissors app in react and have run into a problem. I am testing the app by console.logging the id of the target pic pressed(rock paper or scissors) but the thing is I am console logging the same thing multip

    www.freecodecamp.org

     

Designed by Tistory.