[엘리스 sw 엔지니어 트랙] 49일차 State

오경찬·2022년 6월 19일
0

수업 49일차

리액트의 기초적인 개념들을 정리하고 어떻게 사용하는지 엘리스 플랫폼에서 많이 배운 날이다. 이론적인 부분보다는 실습 위주로 문제를 풀어보았다.

이론

  • Props: Compoment에 원하는 값을 넘겨줄 때 사용, Javascript의 요소라면 제한 없음
    State: Compoment 내에서 유동적으로 변할 수 있는 값을 저장
    이벤트: 웹브라우저가 알려주는 HTML 요소에 대한 사건의 발생
    onClick: Element를 클릭했을 때
    onChange: Element의 내용이 변경되었을 때
    onkeyDown, onKeyUp, onKeyPress: 키보드 입력이 일어났을 때
    onDoubleClick: Element를 더블 클릭했을 때
    onFocus: Element에 Focus되었을 때
    onBlur: Element가 Focus를 잃었을 때
    onSubmit: Form Element에서 Submit 했을 때

State

컴포넌트 자체적으로 지닌 값으로 컴포넌트 내부에서 값을 업데이트할 수 있다.

props vs state
둘 다 컴포넌트에서 사용하거나 렌더링할 데이터를 담고 있는 면에서 비슷하다.
props 값은 부모 컴포넌트에서 설정하고, 컴포넌트 자신은 해당 props를 읽기 전용으로만 사용할 수 있다.
state 값은 컴포넌트 내부에서 설정하고 업데이트할 수 있다.
props 값이 무조건 고정적인 것은 아니다.

  • 부모 컴포넌트의 state를 자식 컴포넌트의 props로 설정하고 자식 컴포넌트에서 특정 이벤트가 발생할 때 부모 컴포넌트의 메서드를 호출하면 props도 유동적으로 사용할 수 있다.

클래스형 컴포넌트의 state

import { Component } from "react";

class Counter extends Component {
    constructor(props) {
       super(props);
       // state의 초기값 설정
       // 객체 형식!
       this.state = {
          number: 0
       };
    }
    render() {
        // state를 조회할 때는 this.state로 조회
        const { number } = this.state;
        return (
            <div>
                <h1>{number}</h1>
                <button 
                    onClick = { () => this.setState({number: number + 1})}
                >
                    +1
                </button>
            </div>
        );
    }
}

export default Counter;

props를 사용하기 위해서는 컴포넌트의 생성자 메서드 (constructor 메서드) 내부에서 super(props)를 호출해야 한다.
super(props)를 호출하면 Component 클래스가 지닌 생성자 함수를 호출해 준다.
컴포넌트의 state는 객체 형식이어야 한다.
render 메서드에서 state를 조회할 때는 this.state 이용

state 객체 안에 여러 값이 있을 때

import { Component } from "react";

class Counter extends Component {
    // state의 초기값 설정
    // 객체 형식!
    state = {
        number: 0,
        fixedNumber: 0
    };
    constructor(props) {
       super(props);
    }
    render() {
        // state를 조회할 때는 this.state로 조회
        const { number, fixedNumber } = this.state;
        return (
            <div>
                <h1>{number}</h1>
                <h2>바뀌지 않는 값: {fixedNumber}</h2>
                <button 
                    onClick = { () => this.setState({number: number + 1})}
                >
                    +1
                </button>
            </div>
        );
    }
}

export default Counter;

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

setState를 사용하여 값을 업데이트하고 난 다음에 특정 작업을 하고 싶을 때는 setState의 두 번째 파라미터로 콜백 함수를 전달하면 된다.

const onClick = () => {
	this.setState({
        number: number + 1
    }, () => {
        console.log("setState 호출");
    })}
};
<button onClick={onClick}>
    +1
</button>

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

setState()는 비동기로 처리된다.
state는 객체이다.
setState가 연속적으로 호출되면 전달 받은 각 state(객체)를 합치고(merging) 합쳐진 단일 객체에 대해 setState()를 실행한다.
merge 과정에서 같은 key를 가지고 있다면 값을 덮어쓴다.
즉, setState()를 연속적으로 호출하면 Batch 처리(일괄 처리)를 한다.
웹 페이지 불필요한 렌더링 횟수를 줄여 좀 더 빠른 속도로 동작하게 만들기 위해서이다.
위 문제를 해결하기 위해 setState에 객체 대신 함수 인자를 전달한다.
인자로 전달한 함수는 이전 상태 (prevState)를 첫 번째 인자로 받고 업데이트가 적용된 시점의 props를 두 번째 인자로 받는다.

함수형 컴포넌트에서 useState 사용하기

v16.8 이후부터 useState 함수를 이용하여 함수형 컴포넌트에서도 state를 이용할 수 있다.
useState 함수를 호출하면 배열이 반환되는데, 첫번째 원소는 현재 상태값이고, 두번째 원소는 상태를 바꾸어 주는 함수이다. (setter 함수)
useState 함수를 호출할 때 초기 상태값을 인자로 보낸다.

mport React, { useState } from 'react';

function Counter() {
    // 배열 비구조화 할당
    const [number, setNumber] = useState(0);
    
    const onIncrease = () => {
        setNumber(number + 1);
    };
    
    const onDecrease = () => {
        setNumber(number - 1);
    };
    
    return (
        <div>
            <h1>{number}</h1>
            <button onClick = {onIncrease}>+1</button>
            <button onClick = {onDecrease}>-1</button>
        </div>
    );

}
export default Counter;

함수형 업데이트

만약 이전의 상태값을 참고하고 싶다면, setState에 함수 인자를 전달하면 된다.
이 함수 인자는 전의 상태값을 인자로 받고 업데이트된 상태값을 반환한다.

// 함수형 업데이트
const onIncrease = () => {
    setNumber(prevNumber => prevNumber + 1);
  }

  const onDecrease = () => {
    setNumber(prevNumber => prevNumber - 1);
  }

state 사용 시 주의사항

state 값을 바꾸어야 할 때는 setState 혹은 useState를 통해 전달받은 setter 함수를 사용해야만 한다.

// 잘못된 코드
this.state.number = this.state.number + 1;
this.state.array = this.state.array.push(2);
this.state.object.value = 5;

const [object, setObject] = useState({a: 1, b: 1});
object.b = 2;

배열이나 객체를 업데이트해야 할 때는 배열이나 객체 사본을 만들고 그 사본에 값을 업데이트한 후 그 사본의 상태를 setState 혹은 setter 함수통해 업데이트한다.

profile
코린이 입니당 :)

0개의 댓글