Front-end

리액트 - 컴포넌트 (2) state

자몽포도 2023. 6. 13. 13:25

목차

1. state

2.클래스형 컴포넌트 state

3.함수 컴포넌트 useState

 

 

 

state


리액트에서 state는 컴포넌트 내부에서 바뀔 수 있는 값을 의미합니다. 리액트에는 두 가지 종류의 state가 있습니다. 하나는 클래스형 컴포넌트의 state, 다른 하나는 함수 컴포넌트에서 useState 함수를 통해 사용하는 state입니다.

 

 

클래스형 컴포넌트의 state


 

class Counter extends Component {
    constructor(props) {
        super(props);
        //state의 초깃값 설정하기
        this.state = {
            number: 0
        };
    }

 

클래스형 컴포넌트 호출부입니다. super를 사용해서 Component 클래스의 생성자를 호출해줍시다.

 

render() {
        const { number } = this.state //state를 조회할 때는 this.state로 조회합니다.
        return (
            <div>
                <h1>{number}</h1>
                <button
                    onClick={() => {
                        this.setState({ number: number + 1 });
                    }}
                >
                    +1
                </button>
            </div>
        );
    }

 

render 함수에서 현재 state를 조회할 때는 this.state를 조회하면 됩니다. 그리고 button 안에 onClick 이벤트를 넣어주었습니다. this.setState 를 통해서 state 값을 바꿀 수 있습니다.

 

 

버튼을 누를 때 마다 1씩 증가합니다.

 

 

state를 constructor에서 꺼내기


constructor 메서드를 선언하지 않고도 state 초깃값을 설정할 수 있습니다. 

 

//after
class Counter extends Component {
    state = {
        number: 0,
        fixNumber: 0
    };

 

 

this.setState에 객체 대신 함수 인자 전달하기


아래 이벤트를 실행하면  number는 예상과 다르게 2가 증가하게 됩니다.

onClick={() => {
    this.setState({ number : number + 1 }); // (1)
    this.setState({number : this.state.number + 2}) // (2)
}}

 

useState는 비동기처리를 합니다. 일반적으로 비동기 논블락킹 환경에서는 작업의 순서에 구애받지 않고 I/O 가 일어나도 제어권을 넘기지 않고 결과를 기다리지 않은채 자신의 작업을 수행하는데요. 

 

(1)의 결과를 기다리지 않고 (2)를 실행할 수 있다는 이야기 입니다. react에서는 가장 최근에 갱신된 값을 제공한다고 하네요. 이러한 예상치 못한 결과를 해결하기 위해서는 setState를 사용할 때 객체 대신에 함수를 인자로 넣어 줄 수 있습니다.

 

이렇게 인자로 함수를 받으면 원하는 결과를 도출할 수 있습니다.

onClick={() => {
    this.setState(preState => ({ 
        number: preState.number + 1      
    }));
    this.setState(preState => ({
        number: preState.number + 2
    }));
}}

 

 

this.setState가 끝난 후 특정 작업 실행하기


setState() 는 두번째 인자로 callback을 받습니다.

 

onClick={() => {
    this.setState(
        {
            number: number + 1
        },
        () => {
            console.log('방금 setState가 호출되었습니다.');
            console.log(this.state);
        }
    )
}}

 

 

 

 

함수 컴포넌트에서 useState


리액트 16.8 이후부터 useState라는 함수를 사용하여 함수 컴포넌트에서도 state를 사용할 수 있게 되었습니다. 이 과정에서 Hooks라는 것을 사용하게 됩니다. 포스팅에서는 useState만 배우고 이후 Hook에 대해 정리하도록 하겠습니다.

 

 

useState 사용하기


 

위 스펙에 따라서 만들어주면 된다. useState 함수의 인자로는 상태의 초기값을 입력해주면 되고 값의 형태는 자유이다. 문자열뿐만 아니라 숫자, 객체 등 제약을 받지 않는다.

 

배열이 반환되는데 첫 번째 원소(state)는 현재 상태입니다. 두번째 원소로는 상태를 바꿔주는 함수가 반환된다.

 

const Say = () => {
    const [message, setMessage] = useState('버튼을 눌러주세요');
    const onClickEnter = () => setMessage('안녕하세요');
    const onClickLeave = () => setMessage('안녕히 가세요!');

    return (
        <div>
            <button onClick={onClickEnter}>입장</button>
            <button onClick={onClickLeave}>퇴장</button>
            <h1>{message}</h1>
        </div>
    )
};

 

 

아래처럼 한 컴포넌트에서 useState를 여러 번 사용할 수도 있습니다.

const Say = () => {
    const [message, setMessage] = useState('버튼을 눌러주세요');
    const onClickEnter = () => setMessage('안녕하세요');
    const onClickLeave = () => setMessage('안녕히 가세요!');

    const [color, setColor] = useState('black');

    return (
        <div>
            <button onClick={onClickEnter}>입장</button>
            <button onClick={onClickLeave}>퇴장</button>
            <h1 style={{color}}>{message}</h1>

            <button style={{ color: 'red' }} onClick={() => setColor('red')}>
                빨간색
            </button>
            <button style={{ color: 'green' }} onClick={() => setColor('green')}>
                초록색
            </button>
            <button style={{ color: 'blue' }} onClick={() => setColor('blue')}>
                파란색
            </button>
        </div>
    )
};