엄코딩의 개발 일지

컴포넌트 상태란?

컴포넌트 상태에 대한 설명은 다음 질문으로 부터 시작된다.

JSX에서 자바스크립트 컬렉션을 <li>요소에 매핑하는 <ul> 태그를 선언했다면 이 컬렉션은 어떻게 채워질까?

 

상태는 리액트의 동적인 부분이다. 이는 컴포넌트의 초기 상태를 선언하고 시간이 지남에 따라 계속 변한다는 것을 의미한다.

 

초기 상태를 가진 컴포넌트가 빈 배열을 렌더링한다고 가정했을 때, 나중에 이 배열이 채워질 수 있다. 이를 상태 변화라고 하며 컴포넌트의 상태가 변할 때마다 자동으로 렌더링된다.

 

컴포넌트 프로퍼티란?

프로퍼티는 데이터를 컴포넌트로 전달하기 위해 사용된다. 새로운 상태가 인수 값인 메서드를 호출하는 대신, 오직 컴포넌트가 렌더링될 때만 전달된다. 즉 JSX 요소에 프로퍼티 값을 전달한다. 

 

즉, 프로퍼티는 JSX 컨텍스트에서 XML 형식으로 호출되기 때문에 어트리뷰트(attributes)라 불린다.

 

프로퍼티는 컴포넌트의 초기 렌더링 후에 변경되지 않는 부분이 상태와 다르다.

 

컴포넌트 상태 설정

지난번 포스팅을 토대로 react app을 만든후 module.js라는 파일을 만들고 아래와 같은 코드를 작성했다.

import React, { Component } from 'react';

export default class MyComponent extends Component{
    state = {
        heading : 'React Awesomesauce ( Busy )',
        content : 'Loading...'
    }

    render(){
        const { heading, content } = this.state;

        return (
            <main>
                <h1>{heading}</h1>
                <p>{content}</p>
            </main>
        );
    }
}

위 코드는 초기 상태를 가진 컴포넌트이며 JSX는 heading, content 2개의 상태 프로퍼티에 의존하고 있다.

이러한 초깃값 설정은 렌더링 시 예기치 못한 일을 방지해준다.

위 코드 실행 결과 출력되는 화면은 다음과 같다.

 

 

이제 컴포넌트를 렌더링하고 상태 값 변경으로 재렌더링하는 코드를 살펴보자.

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import MyComponent from './module';

const myComponent = ReactDOM.render(
    (<MyComponent/>),
    document.getElementById('root')
);

setTimeout(()=> {
    myComponent.setState(
        {
            heading: 'React Awesomesauce',
            content: 'DONE!',
        }
    );
},3000);

 

컴포넌트는 일단 기본 상태로 렌더링된다.  그리고 setTimeout() 호출을 통해서 3초 후에 2개의 상태 프로퍼티 값을 변경한다.

그리고 UI에 자동 반영된다.

 

컴포넌트 상태 병합

리액트 컴포넌트의 상태를 설정할 때 setState()에 전달한 객체와 컴포넌트의 상태값을 병합한다.

이를 통해 상태의 나머지 부분을 그대로 남겨두고 컴포넌트 상태의 일부만을 설정할 수 있기 때문에 매우 유용하다.

 

import React, { Component } from 'react';

export default class MyComponent extends Component{
    state = {
        first : 'loading...',
        second : 'loading...',
        third : 'loading...',
        fourth : 'loading...',
        doneMessage : 'finished!'
    }

    render(){
        const { state } = this;

        return(
            <ul>
                {Object.keys(state)
                .filter(key => key !== 'doneMessage')
                .map(key => (
                    <li key = {key}>
                        <strong>{key}: </strong>
                        {state[key]}
                    </li>
                ))}
            </ul>
        )
    }
}

위 코드를 통해서 컴포넌트는 key값이 doneMessage인 값을 제외하고 상태의 키와 값을 렌더링한다.

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import MyComponent from './module';

const myComponent = ReactDOM.render(
    (<MyComponent/>),
    document.getElementById('root')
);

setTimeout(()=> {
    myComponent.setState(
        {
            first : 'done!'
        }
    );
},1000);

setTimeout(()=> {
    myComponent.setState(
        {
            second : 'done!'
        }
    );
},2000);

setTimeout(()=> {
    myComponent.setState(
        {
            third : 'done!'
        }
    );
},3000);

setTimeout(()=> {
    myComponent.setState(
        {
            fourth : myComponent.state.doneMessage
        }
    );
},4000);

 

위코드를 통해 1,2,3,4초 마다 갱신되는 UI를 확인할 수 있다.

위코드에서 fourth 값은 처음 3개와 달라보인다. 새로운 객체를 기존 상태로 병합하는 대신, 함수를 전달할 수 있다.

이 함수는 컴포넌트의 현재 상태 값을 인수로 가진다. 현재 상태 값을 기반으로 상태를 변경할 경우에 유용하게 쓰일 수 있다.

 

 

 

 

참고자료 : 리액트&리액트 네이티브 통합 교과서