React

4. React 컴포넌트의 상태 객체

하늘을난모기 2018. 12. 2. 18:22

4. React 컴포넌트의 상태 객체

속성은 현재 컴포넌트 내부에서 수정할 수 없다. 해당 컴포넌트 생성 시에 전달 받는 값이기 때문이다.

속성 변경 없이 어떻게 뷰를 갱신할까?

상태 객체를 사용하면 된다.

상태(state)는 React 컴포넌트에 데이터를 저장하고, 데이터의 변경에 따라 자동으로 뷰를 갱신하도록 하는 핵심 개념이다.

4.1 React 컴포넌트의 상태란?

상태는 변경 가능한 데이터 저장소.

상태 객체에 접근할 때는 이름을 사용 (this.state)

변경 하고 싶은 작은 단위의 부분만 갱신.

ex) 뷰가 갱신되지 않는 안티 패턴 (속성은 변경되지 않는다.)

let inputValue = 'Texas'
class Autocomplete extends React.Component {
    updateValues() {
        this.props.inputValue = 'California'
        inputValue = 'California'
        this.inputValue = 'California'
    }
    render() {
        return(
            <div>
                {this.props.inputValue}
                {inputValue}
                {this.inputValue}
            </div>
        )
    }
}

4.2 상태 객체 다루기

4.2.1 상태 객체에 접근하기

this 키워드로 접근

ex) JSX에서 상태 렌더링하기 (Clock 예제)

class Clock extends React.Component {
    render() {
        return <div>{this.state.currentTime}</div>
    }
}

ReactDOM.render(
    <Clock/>,
    document.getElementById('content')
)

Uncaught TypeError: Cannot read property 'currentTime' of null 오류 발생

4.2.2 초기 상태 설정하기

ex) 상태 초기화

class MyFancyComponent extends React.Component {
    constructor(props) {
        super(props)
        this.state = {...}
    }
    render() {
        ...
    }
} 

ex) 상태 객체 배열 담아보기

class Content extends React.Component {
    constructor(props) {
        super(props)
        this.state = {
            githubName: 'KimHunJin',
            skills: [
                'java',
                'android',
                'blockchain',
                'react'
            ]
        }
    }
    render() {
        ...
    }
}                

4.2.3 상태 갱신하기

this.setState(data, callback)를 사용하여 상태 변경

setState()함수는 비동기로 작동

ex) 상태를 이용한 Click 컴포넌트 구현

class Clock extends React.Component {
    constructor(props) {
        super(props)
        this.launchClock()
        this.state = {
            currentTime: (new Date()).toLocaleString('en')
        }
    }
    launchClock() {
        setInterval(() => {
            console.log('updating time..')
            this.setState({
                currentTime: (new Date()).toLocaleString('en')
            })
        },1000)
    }

    render() {
        console.log('Rendering Clock...')
        return <div>{this.state.currentTime}</div>
    }
}

setState()를 사용하지 않고 직접 상태를 변경하는 것은 안티패턴이므로 피해야 한다.

4.3 상태 객체와 속성

비고 상태 객체 속성
클래스 멤버 O O
변경 여부 가능 불가능
전달 해당 컴포넌트 자체에서 정의 부모 컴포넌트에서 전달

4.4 상태비저장 컴포넌트

상태비저장 컴포넌트 (stateless component)는 상태 객체가 없으며, 컴포넌트 메서드 또는 다른
React의 라이프사이클 이벤트 또는 메서드를 갖지 않는다.
상태비저장 컴포넌트의 목적은 오직 뷰를 렌더링 하는 것이다.

ex) 상태 비저장 컴포넌트 Link (함수로 선언해라)

function Link(props) {
    return <a href={props.href} taget="_blank" className="btn btn-primary">
    {props.text}</a>
}
ReactDOM.render(
    <Link text='Buy React Quickly'
    href='https://www.github.com/KimHunJin/Study-Book'/>,
    document.getElementById('content')
)

상태비저장 컴포넌트는 상태를 가질 수 없다. 하지만, propTypes와 defaultProps를 프로퍼티로 가질 수 있다.

상태비저장 컴포넌트에서는 엘리먼트 참조(refs)를 사용할 수 없다.

4.5 상태비저장 컴포넌트와 상태저장 컴포넌트의 비교

상태비저장 컴포넌트라 하더라도 반드시 정적인 것은 아니다.

상태비저장 컴포넌트를 가능한 많이 사용하는 것을 권장한다.

ex) 피해야 하는 방식

const DigitalDisplay = function(props) {
    return <div>{DigitalDisplay.locale(props.time)}</div>
}
DigitalDisplay.locale = (time) => {
    return (new Date(time)).tolocaleString('EU')
}

ex) 좋은 패턴

const DigitalDisplay = function(props) {
    const locale = time => (new Date(time)).toLocaleString('EU')
    return <div>{locale(props.time)}</div>
}

상태 비저장 컴포넌트는 단순하게 유지해야 한다. 상태 객체나 메서드를 추가하지 말자.

요약

  • 상태 객체는 변경할 수 있다. 속성은 변경할 수 없다.
  • 컴포넌트 클래스의 생성자에서 this.state = ... 를 사용하거나, createClass()를 사용하는 경우
    getInitialState를 호출하여 컴포넌트의 초기 상태 객체를 설정할 수 있다.
  • this.setState는 상태 객체 전체가 아니라 전달한 항목만 갱신한다.
  • {}는 JSX 코드에서 변수를 출력하고 자바스크립트를 실행할 때 사용한다.
  • 상태 객체는 this.state.NAME으로 접근한다.
  • 상태비저장 컴포넌트는 React를 다룰 때 선호되는 방식이다.