본문 바로가기
프론트엔드/React

클래스형 컴포넌트

by alswlfl 2022. 12. 2.

→ 현재는 함수형 컴포넌트를 사용하지만, 나중에 컴포넌트를 사용하는 프로젝트를 유지보수하거나, 함수형 컴포넌트+Hooks로 못하는 작업의 경우 등 클래스형 컴포넌트를 써야하는 상황 존재

<기본 형식>

import React, {Component} from 'react';

class App extends Component{//class키워드 필요, Component로 상속 받아야함
	state={//constructor없이 바로 state초기값 설정 가능, 객체 형식monsters:[],
        userInput:"",
    };
    onClick={()=>{//this.setState 함수로 state 값 변경 가능this.setState({number:number+1});
    }}
	render(){//render()메소드 필요const name='react';
        return <div className="react">{name}</div>
   	}
}

<함수형 vs 클래스형>

  • 함수형 코드
import React from 'react';

function Hello({ color, name, isSpecial }) {
  return (
    <div style={{ color }}>
      {isSpecial && <b>*</b>}
      안녕하세요 {name}
    </div>
  );
}

Hello.defaultProps = {
  name: '이름없음'
};

export default Hello;
  • 클래스형 코드
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;

[클래스형 컴포넌트 특징]

  1. render() 메서드 꼭 존재해야함 (해당 메서드에서 렌더링하고 싶은 JSX 반환)
  2. props 조회 할 때, this.props 로 조회
  3. defaultProps를 설정하는 것은 함수형과 똑같이 하거나, 클래스 내부에 static 키워드와 함께 선언 가능
  4. 클래스형 컴포넌트에서 커스텀 메서드를 만들 때, render함수 내부에서 선언 가능하지만 일반적으로 클래스 안에 커스텀 메서드를 선언
    1. 클래스 내부에 종속된 함수 → “메서드”
    2. 클래스에서 커스텀 메서드 만들 때 보통 이름을 handle…이라고 지음(꼭 지킬 필요는 없음)

커스텀 메서드 만들기

import React, { Component } from "react";

class Counter extends Component {
  handleIncrease() {
    console.log("increase");
  }
  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는 컴포넌트 인스턴스를 가르켜야 하는데, 현재 구현한 메서드에서 this를 조회하려고 하면 컴포넌트 인스턴스를 가르키지 않게됨

→ 우리가 만든 메서드들을 이벤트로 등록하게 되는 과정에서 각 메서드와 컴포넌트의 인스턴스의 관계가 끊겨버리기 때문

→ event handler함수가 호출될 때의 this는 컴포넌트 내부에서 선언한 메소드 객체를 가리키는 것이 아니라 전역객체(window)를 의미

#TIL19, React | this와 bind()

 

#TIL19, React | this와 bind()

개인 공부를 위해 작성했습니다State & Event에 대해 공부하던 중, this와 bind의 개념을 정립하고자 기록해본다.객체지향 언어에서의 일반적인 this는 현재 객체를 지칭하지만, js의 this는 실행할 때의

velog.io

⭐️ 엘리먼트, 인스턴스

엘리먼트(Element): 실제로 화면에 렌더링 할 DOM 노드들의 정보를 React에게 알려주기 위한 수단(DOM 엘리먼트, 컴포넌트 엘리먼트)

  • DOM 엘리먼트: 엘리먼트의 type의 태그 이름에 해당하는 문자열인 경우(소문자로 시작)
  • React가 실제로 화면에 렌더링 하는 대상
  • 컴포넌트 엘리먼트: 엘리먼트의 type이 컴포넌트 클래스/함수인 경우(대문자로 시작)
  • 사용자가 직접 정의한 컴포넌트 표현, 입력으로 props를 받으면 렌더링 할 앨리먼트 트리 반환
  • 한 컴포넌트를 정의하는데 있어 또 다른 컴포넌트 사용 가능

컴포넌트 인스턴스: 클래스로 선언된 컴포넌트들만 인스턴스를 가짐

  • 컴포넌트 클래스 내부에서 this 키워드를 통해 참조하는 대상에 해당
  • 함수형 컴포넌트는 인스턴스 갖지 않음

[React] 엘리먼트, 컴포넌트, 인스턴스 개념

 

[React] 엘리먼트, 컴포넌트, 인스턴스 개념

1. 엘리먼트 (Element) 실제로 화면에 렌더링 할 DOM 노드들의 정보를 React에게 알려주기 위한 수단이다. DOM 노드 혹은 컴포넌트를 표현하는 JavaScript의 일반 불변 객체(Plain Immutable Object)에 해당한다.

it-eldorado.tistory.com

[해결 방법]

  1. 클래스의 생성자 메서드 constructor에서 bind 작업하기
    constructor(props) {
        super(props);
        this.handleIncrease = this.handleIncrease.bind(this);
        this.handleDecrease = this.handleDecrease.bind(this);
      }
    
    • super(props)를 호출하는 것은 클래스가 컴포넌트로서 작동할 수 있도록 해주는 Component쪽에 구현되어 있는 생성자 함수 먼저 실행해주고, 작업 하겠다는 의미
  2. 화살표 함수 문법 사용 →  화살표 함수 사용해서 메서드 구현하는 것은 클래스에 특정 속성을 선언 할 수 있게 해주는 class-properties 문법 사용(정식 문법 아님)
handleIncrease = () => {
    console.log("increase");
  };
  handleDecrease = () => {
    console.log("decrease");
  };

 

     3. onClick에서 새로운 함수를 만들어서 전달하는 것(비추천) → 렌더링 할 때마다 함수가 새로 만들어지기 때문에

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

상태 선언

  • 클래스형 컴포넌트에서 상태를 관리 할 때에는 state 사용
  • state는 무조건 객체 형태
  • state조회하려면 this.state를 조회
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.setState 함수 사용
handleIncrease = () => {
    this.setState({
      counter: this.state.counter + 1,
    });
  };
  handleDecrease = () => {
    this.setState({
      counter: this.state.counter - 1,
    });
  };

→ 클래스형 컴포넌트의 state에서 객체 형태의 상태를 관리해야 한다면, 불변성을 관리해주면서 업데이트 해야함

handleIncrease = () => {
    this.setState({
      counter: this.state.counter + 1,
    });
		this.setState({
		      counter: this.state.counter + 1,
		    });
  };
  • 위 코드와 같이 setState를 두 번 사용하면서 1을 더해주는 작업을 두 번하지만, 실제로는 2가 더해지지 않음
  • setState를 한다고 상태가 바로 바뀌는것이 아님(비동기적으로 업데이트됨). setState는 단순히 상태를 바꾸는 함수가 아니라, 상태로 바꿔달라고 요청해주는 함수

[해결 방법] 콜백함수 넣어줌

handleIncrease = () => {
    this.setState(
      {
        counter: this.state.counter + 1,
      },
      () => {
        console.log(this.state.counter);
      }
    );
  };

'프론트엔드 > React' 카테고리의 다른 글

리액트 개발 시 사용하면 편리한 도구  (0) 2022.12.02
LifeCycle Method  (0) 2022.12.02
Immer  (0) 2022.11.24
Context API  (0) 2022.11.24
커스텀 Hooks 만들기  (0) 2022.11.24