리액트기초 ( State )

taehyung·2023년 9월 19일

React.js

목록 보기
5/24

클래스형 컴포넌트와 함수형 컴포넌트의 State

props 부모 컴포넌트에서 설정된 값이며, 직접적인 변경이 불가능합니다. ( 불변성 ) Immutable Data 즉, 변하지 않는 데이터입니다.
State 컴포넌트 내부에서 관리되는 값을 의미하며, 변경이 가능하고 변경에 따른 리렌더링이 이루어집니다.

클래스형 컴포넌트의 State

생성자함수

  • super(props) : 현재 컴포넌트가 상속받고 있는 리액트의 Component 클래스가 지닌 생성자 함수를 호출해줍니다.
  • this.state : 초기값 설정, 객체형식 이어야 합니다.
  • this.setState( state ) : 현재 컴포넌트의 state 의 값을 설정합니다. 변경되면 View 리렌더링
import React, { Component } from "react";
import fergment from "react";

class Counter extends Component {
  constructor(props) {
    super(props); //클래스형 컴포넌트 생성자에서는 반드시 호출해야합니다.
	console.log(this.props); // super(props) 사용이유에 대해 알아보세요
    this.state = { // 상태관리를 할 변수들을 객체 형태로 선언합니다.
      number: 0,
      name : "" //등등
    };
  }
  render() {
    const { number, name } = this.state; // 비구조화 할당 문법
    console.log(this.props); // super(props) 사용이유에 대해 알아보세요
    console.log(this) // Counter{...} this 는 현재 컴포넌트를 가리킵니다. [[prototype]]는 Componenet 입니다.
    return (
      <fergment>
        <div>{number}</div>
        <div>
          <button
            onClick={() => {
              this.setState({ number: number + 1 }); // state의 값변경 ( 리렌더링 )
            }}
          >
            increase
          </button>
        </div>
      </fergment>
    );
  }
}
export default Counter;

state를 생성자 함수에서 꺼내기

생성자 함수를 정의하지 않고 아래와같이 간략하게 사용할 수 있습니다.

import React, { Component } from "react";
import fergment from "react";

class Counter extends Component {
   state = { // 상태관리를 할 변수들을 객체 형태로 선언합니다.
      number: 0,
      name : "" //등등
    };
  render() {
    const { number, name } = this.state; // 비구조화 할당 문법
    return (
      <fergment>
			...code
      </fergment>
    );
  }
}
export default Counter;

SetState 는 비동기

setState를 통하여 상태를 업데이트할 때에는 비동기적으로 업데이트 됩니다.

class Counter extends Component {
  state = { //state 설정
    number: 0,
    random: 0,
  };

  render() {
    const { number, random } = this.state; // 변수할당

    return (
      <fergment>
        <div>{number}</div>
        <div>
          <button
            onClick={() => {
              this.setState({ number: number + 1 });
              this.setState({ number: this.state.number + 1 });
            }}
          >
            increase
          </button>
        </div>
      </fergment>
    );
  }
}

위와같이 한번의 이벤트핸들러 안에서 2번의 상태를 업데이트하면 어떻게 될까요? 상식적으론 2씩 증가해야하지만 그렇지 않습니다.

setState가 비동기인 이유는 무엇일까요?
setState가 동기적으로 작동한다면 state의 변경에따라 페이지 리렌더링의 수가 상당히 증가할 것입니다. 성능이슈가 발생되겠죠?
위와같은 이유로 setState는 상태를 한번에 종합해서 리렌더링하기위해 비동기로 작업한것입니다.

state 객체의 같은 키값을 가진 경우에는 가장 마지막 실행된 값으로 덮어지게 됩니다.

this.setState({ number: this.state.number + 1 });

이부분이 되겠죠?

해결책
setState의 인자로 함수를 전달하면 됩니다.

  • prevState : 기존 상태
  • props : 현재 컴포넌트의 props ( 생략가능 )
	 <button
            onClick={() => {
              this.setState((prevState) => {
                return {
                  number: prevState.number + 1,
                };
              });
              this.setState((prevState) => {
                return {
                  number: prevState.number + 1,
                };
              });
            }}
          >
            increase
          </button>

setState 이후에 실행되는 callback()

setState 로 값을 설정한 후에 실행되는 callback 함수는 두번째 인자로 넣어주면 됩니다.

	 <div>
          <button
            onClick={() => {
              this.setState({ number: number + 1 }, () => {
                alert("변경후의값은:" + number + "입니다");
              });
            }}
          >
            increase
          </button>
        </div>
     </button>

함수형 컴포넌트의 useState

16.8 이전 버전에서 함수형 컴포넌트는 상태관리를 할 수 없었습니다. 이후로 Hooks가 도입되면서 함수형 컴포넌트의 단점들이 사라졌는습니다. 오늘은 useState Hook에 대해 포스팅하겠습니다.

const SayMessege = () => {
  const [messege, setMessege] = useState("");
  //구조분해 할당 기억나시나요? useState() 함수의 인자는 1번째 배열에 저장되고 2번째 배열은 1번째 배열에 값을 적용해주는 함수가 들어있습니다.

  const Hi = () => {
    setMessege("어서오세요");
  };
  const Bey = () => {
    setMessege("안녕히가세요");
  };

  return (
    <div>
      <div>{messege}</div>
      <button onClick={Hi}>입장</button>
      <button onClick={Bey}>퇴장</button>
    </div>
  );
};

export default SayMessege;

주의사항 클래스형, 함수형 모두 상태관리를 위해서는 setter 를 사용하여 값을 변경하여야합니다.

참조타입 State

참조타입 데이터의 상태관리는 방법이 다릅니다. 이전에 자바스크립트의 메모리 할당방식에대해 이야기한적이 있습니다.

리액트는 상태를 관리하는 변수의 값이 변했을 때 화면을 리렌더링 합니다. 즉, 데이터가 저장된 메모리 주소가 바뀌었을 때 리렌더링 한다는 말입니다.

참조타입 데이터는 저장된 메모리의 주소를 변경하려면 어떻게해야했었나요? 리액트에서 참조타입 데이터를 리렌더링하려면 완전히 새로운 객체를 만들어주어야 합니다.

const Animals = () => {
	const [animals, setAnimal] = useState({name:"",age:""});

	setAnimals({...animals,race:""})
}
profile
Front End

0개의 댓글