이다닷

[React] Day 26 - 클래스형 컴포넌트 본문

React

[React] Day 26 - 클래스형 컴포넌트

이다닷 2023. 10. 9. 00:31

📌클래스형 컴포넌트를 사용하는 이유는 많을 수 있다.

  -> 프로젝트를 유지보수하는 경우, 함수형 컴포넌트 + Hooks로 못하는 작업일 때도 있고, 옛날에 만들어진 리액트 관련 라이브러리의 경우에는 Hooks가 지원이 안되는 경우가 있다.

이렇게 클래스형 컴포넌트를 잘 사용하지는 않지만 사용해야하는 상황이 생길 수 있다.

 

➡️클래스형 컴포넌트를 사용해서 Hello.js 변경.

 

📌클래스형 컴포넌트에서 있어야하는 것

   -> 클래스형 컴포넌트에는 render() 함수가 무조건 있어야 한다. 그리고, props를 조회하고 싶을 때에는 this.props를 조회하면 된다.

Hello.js 변경

import React, { Component } from 'react';

class Hello extends Component {
  static defaultProps = {
    name: '이름없음'
  };
  render() {
    const { color, name, isSpecial } = this.props;
    return (
      <div style={{ color }}>
        {isSpecial && <b>*</b>}
        안녕하세요 {name}
      </div>
    );
  }
}

export default Hello;

 

➡️클래스형 컴포넌트를 사용해서 Counter.js 변경

 

📌커스텀 메서드 만들기

const onIncrease = () => {
  dispatch({ type: 'INCREMENT' });
};

원래라면 버튼을 클릭했을때 특정 작업을 실행하고 싶다면 그냥 컴포넌트 안에 이렇게 선언 해주면 된다.

하지만 클래스형 컴포넌트는 조금 다르다. 그렇다면 클래스형 컴포넌트는 클래스 안에 커스텀 메세지를 선언해주면 된다.

 

Counter.js 변경

import React, { Component } from 'react';

class Counter extends Component {
  //
  handleIncrease() {
    console.log('increase');
    console.log(this);
  }

  handleDecrease() {
    console.log('decrease');
  }

  render() {
    return (
      <div>
        <h1>0</h1>
        <button onClick={this.handleIncrease}>+1</button>
        <button onClick={this.handleDecrease}>-1</button>
      </div>
  //
    );
  }
}

export default Counter;

 

이렇게 커스텀 메세지를 전달 해 줄 수 있다.

하지만 지금까지 바꾼 내용으로는 제대로된 this 값을 출력해주지 못한다. 

  -> 이렇게 되는 이유는, 방금 만든 메서드들과 각 button들의 이벤트로 등록하게 되는 과정에서 각 메서드와 컴포넌트 인스턴스의 관계가 끊겨버리기 때문이다.

 

이를 해결하는 방법에는 세 가지가 있다.

  -  첫번째는 클래스 생성자 메서드 constructor에서 bind 작업을 해주는 것이다.

constructor(props) {
    super(props);
    this.handleIncrease = this.handleIncrease.bind(this);
    this.handleDecrease = this.handleDecrease.bind(this);
  }

    - 이 코드를 추가해주고 나면 현재 컴포넌트 인스턴스가 잘 나타난다.

    - bind 함수를 이용하면 해당 함수에서 가리킬 this를 직접 지정해 줄 수 있다. 

 

  -  두번째는 커스텀 메세지를 선언할 때 화살표 함수 문법을 사용해서 작성하는 것이다.

handleIncrease = () => {
    console.log('increase');
    console.log(this);
  };

  handleDecrease = () => {
    console.log('decrease');
  };

    -  가장 편하고, 가장 많이 이용하는 방법이다.

 

  -  세번째는 onClick에서 새로운 함수를 만들어서 하는 방법이다.

    - 하지만 이 방법은 렌더링 할 때마다 함수가 새로 만들어지기 때문에 나중에 컴포넌트를 최적화 할 때 까다롭다.

return (
  <div>
    <h1>0</h1>
    <button onClick={() => this.handleIncrease()}>+1</button>
    <button onClick={() => this.handleDecrease()}>-1</button>
  </div>
);

 

📌클래스형 컴포넌트에서 상태 관리하기

    -> 클래스형 컴포넌트에서 상태를 관리 할 때에는 state라는 것을 사용한다. state를 선언 할 때에는 constructor 내부에서 this.state를 설정해주면 된다.

 

Counter.js 변경

import React, { Component } from 'react';

class Counter extends Component {
  constructor(props) {
    super(props);
    this.state = {
      counter: 0
    };
  }
  handleIncrease = () => {
    console.log('increase');
    console.log(this);
  };

  handleDecrease = () => {
    console.log('decrease');
  };

  render() {
    return (
      <div>
        <h1>{this.state.counter}</h1>
        <button onClick={this.handleIncrease}>+1</button>
        <button onClick={this.handleDecrease}>-1</button>
      </div>
    );
  }
}

export default Counter;

 

➡️상태 업데이트하기

- 상태를 업데이트 할 때에는 this.state를 사용하면 된다.

 

Counter.js 변경

import React, { Component } from 'react';

class Counter extends Component {
  state = {
    counter: 0
  };
  handleIncrease = () => {
    this.setState({
      counter: this.state.counter + 1
    });
  };

  handleDecrease = () => {
    this.setState({
      counter: this.state.counter - 1
    });
  };

  render() {
    return (
      <div>
        <h1>{this.state.counter}</h1>
        <button onClick={this.handleIncrease}>+1</button>
        <button onClick={this.handleDecrease}>-1</button>
      </div>
    );
  }
}

export default Counter;

 

➡️setState의 함수형 업데이트

  -> 함수형 업데이트는 보통 한 함수에서 setState를 여러번에 걸쳐서 해야 되는 경우에 사용하면 유용하다.

 

Counter.js 변경

import React, { Component } from 'react';

class Counter extends Component {
  state = {
    counter: 0,
    fixed: 1
  };
  handleIncrease = () => {
    this.setState(state => ({
      counter: state.counter + 1
    }));
    this.setState(state => ({
      counter: state.counter + 1
    }));
  };

  handleDecrease = () => {
    this.setState(state => ({
      counter: state.counter - 1
    }));
  };

  render() {
    return (
      <div>
        <h1>{this.state.counter}</h1>
        <button onClick={this.handleIncrease}>+1</button>
        <button onClick={this.handleDecrease}>-1</button>
        <p>고정된 값: {this.state.fixed}</p>
      </div>
    );
  }
}

export default Counter;