블로그 내용은
Programming with Mosh React Tutorial for Beginners [React js]
을 공부하는 과정에서 작성되었습니다.

<작성 코드>

import React, { Component, Fragment } from 'react';

class Counter extends Component {
    state = {
        count : 1,  
        tags: ["tag1", "tag2", "tag3"]     
    };
    render() { 
        return (
            <Fragment>                              
                <span  className={this.getBadgeClasses()}>{this.formatCount()}</span>
                <button className="btn btn-secondary btn-sm">Increment</button>
                <ul>{this.state.tags.map(tag => <li key={tag} >{tag}</li>)}</ul>
            </Fragment>
        );
    }
    getBadgeClasses() {
        let classes = "badge m-2 badge-";
        classes += this.state.count === 0 ? "warning" : "primary"; //엘로우 블루
        return classes;
    }
    formatCount() {
        const {count} = this.state; 
        const x = "ZERO";
        return count === 0 ? x : count;
    }
}

export default Counter;

Handling Events

이제 사용자가 버튼을 클릭하면 카트에 숫자가 증가하도록 코드를 작성해보자. 바닐라 자바스크립트로는 addEventListener와 비슷한 개념이다.

클릭시 작동되는 함수를 작성하고, 클릭할 버튼을 편집한다.

handleIncrement () {
        console.log("Increment Clicked", this);
        // 클릭시 호출될 메서드
<button onClick={this.handleIncrement} className="btn btn-secondary btn-sm">Increment</button>
// Button에 onClick을 이용해서 메서드와 연결

여기서 주의할 부분은 JSX에서는 handleIncrement()가 아닌 handleIncrement으로 코드를 작성시켜야 한다는 점이다. 호출시킨 결과를 넘기는 것이 아니고 클릭할때마다 호출해야하기 때문이다.

위와 같이 작성하면, 결과로는 클릭 시 Increment Clicked는 출력되지만 this는 undefined로 출력될 것이다. 문제를 해결해보자

Binding

위와 같은 결과가 나오는 이유는 자바스크립트에서 this가 가리키는 것이 Counter 객체가 될 이유가 없기 때문이다. 왜냐하면 객체 안에 메서드에서 그 메서드가 포함된 object를 가리키는 것이 this이기 때문이다. 그렇기 때문에 메서드와 this의 관계를 위해 "바인딩"을 사용한다.

handleIncrement = () => {
        console.log("Increment Clicked", this);
    }

다음과 같이 애로우 함수를 사용하여 바인딩을 구현해주면된다. (생성자를 사용한 기초적인 바인딩은 아래를 참고)
https://ko.reactjs.org/docs/handling-events.html

만약에 매개변수가 있다면 익명함수처리해서 넘겨야한다.

() => handleIncrement(매개변수명)

updating state

handleIncrement = () => {
 		console.log("Increment Clicked", this);
		this.state.count++;     
    }

이제 클릭시 값의 증가를 구현하기 위해 코드를 변경했다.
하지만 실제로는 클릭마다 값이 증가하지 않는다. 이유는 리액트는 동적으로 state를 관리하기 위해서 setState()메서드를 사용하기 때문이다.

handleIncrement = () => {
        console.log("Increment Clicked", this);
        this.setState({count: this.state.count + 1});
    } 

위와 같이 변경해주면 정상적으로 작동하는 것을 확인할 수 있다.

setState() 특성

setState()의 특성을 살펴보겠습니다.

  1. setState()메서드는 state가 변경된 것이 있다면 리액트에 알려주는 메서드이다.
  2. 그리고 리액트는 state가 변경된 것이 있다면 render()을 다시 호출한다. 이를 리-렌더링이라 부른다
  3. 그런데 setstate()는 비동기식으로 작동하기 때문에 우리는 언제 render을 호출하는지 기대할 수 없다.
  4. 어쨌든 render가 호출되면 virtual DOM을 만든다. 리액트는 new tree와 old tree를 비교해서 변경된 element만 업데이트 시킵니다.

    실제로 버튼을 클릭하지만 변경되는 것은 formatCount()임으로 span태그와 formatCount()만 업데이트 시킵니다.
render() { 
        return (
            <Fragment>                              
                <span  className={this.getBadgeClasses()}>{this.formatCount()}</span>
                <button className="btn btn-secondary btn-sm">Increment</button>
                <ul>{this.state.tags.map(tag => <li key={tag} >{tag}</li>)}</ul>
            </Fragment>
        );
    }

참고자료
https://ko.reactjs.org/docs/getting-started.html

https://www.youtube.com/watch?v=Ke90Tje7VS0&t=916s

profile
익숙한 것에 작별을 고해야한다

0개의 댓글