[React] state

🌊·2021년 12월 7일
0

React

목록 보기
3/20

state

컴포넌트 내부에서 바뀔 수 있는 값을 의미한다.

props는 컴포넌트가 사용되는 과정에서 부모 컴포넌트가 설정하는 값이고, 컴포넌트 자신은 props를 읽기 전용으로 사용할 수 있다.

✅ state 종류

  • 클래스형 컴포넌트 state
  • 함수 컴포넌트 state (useState 함수 사용)

✅ 클래스형 컴포넌트 state (Counter.js)

컴포넌트에 state를 설정할 때는 constructor 메서드를 작성하여 설정한다.
컴포넌트의 state는 객체 형식이어야 한다.

constructor(props) {
    super(props);
    this.state = {
      number: 0,
    };
  }

constructor: 컴포넌트의 생성자 메서드

  • 반드시 super(props)를 호출해주어야 한다.
  • super 함수가 호출되면 Component 클래스가 지닌 생성자 함수를 호출해준다.
render() {
    const { number } = this.state;
    return (
      <div>
        <h1>{number}</h1>
        <button
          onClick={() => {
            this.setState({ number: number + 1 });
          }}
        >
          +1
        </button>
      </div>
    );
  }

button의 onClick은 button이 클릭될 때 호출시킬 함수를 설정한다. (이벤트를 설정한다고 말한다.) 이벤트로 설정할 함수를 넣어줄 때는 화살표 함수 문법을 사용하여 넣어주어야 한다.

this.setState 함수를 통해서 state 값을 바꿀 수 있게 한다.

  • state 값을 업데이트할 때는 상태가 비동기적으로 업데이트 된다.
  • state를 업데이트하더라도 즉시 반영되지 않는다는 뜻

constructor 메서드를 사용하지 않고 state 지정하기 (Counter.js)

state = {
    number: 0,
    fixedNumber: 0,
  };

setState에 함수 인자 전달

setState를 호출한 직후에 this.state에 접근하는 것은 좋지 않다. 이전 상태를 기반하여 상태를 변경해야 한다면 updater 함수를 사용하는 것이다.
updater 함수를 setState 메소드의 첫번째 인자로 넘기는 방식으로 사용할 수 있다.

onClick={() => {
  this.setState((prevState) => {
    return {
      number: prevState.number + 1,
    };
  });
}}

updater의 인자(prevState)는 최신상태를 기반으로 하기 때문에 두번을 호출하면 2가 더해진다. 하지만 this.setState({ number: number + 1 });을 두번 호출하게 되면 리액트는 이것을 하나로 합쳐서 변경하기 때문에 1만 증가된다.

setState callback 함수 등록

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

this.setState()는 파라미터가 updater와 callback 함수로 되어 있다.

updater 부분

  • (state, props) => stateChange 형태를 가진 함수
  • updater 함수로 전달된 state와 props는 최신값이 보장된다.
(prevState) => ({
  number: prevState.number + 1,
})

callback 함수 부분

() => {
  console.log("방금 setState가 호출되었습니다.");
}

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

리액트 16.8 이후 버전에서 사용 가능한 함수이다. Hooks 개념이 필요하다.

배열의 비구조화 할당

객체 비구조화 할당과 비슷한 모습을 가진다.


const array = [1, 2];


const one = array[0];
const two = array[1];


const [one, two] = array;

array 안에 있는 값을 one, two에 할당하는 코드, 배열의 비구조화 할당을 통해서 표현할 수 있다.

useState 사용하기 (Say.js)

useState 함수를 호출하면 배열이 반환된다.

  • 배열의 첫 번째 원소 : 현재 상태 (message)

  • 배열의 두 번째 원소 : 상태를 바꾸어주는 함수 (세터(Setter) 함수) (setMessage)

  • 배열의 원소 이름은 자유롭게 정해주어도 상관없다.

import React, { useState } from "react";

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>
  );
};

export default Say;

useState 함수의 인자에는 상태의 초깃값을 넣어준다.useState(['??', ''])라고 초깃값을 넣어주게 되면 화면 처음 message의 값은 '??'이 된다.
클래스형 컴포넌트에서 state의 초깃값은 객체 형태를 넣어주어야 하지만, useState의 초깃값은 반드시 객체가 아니여도 상관 없다.

배열의 첫 번째 원소는 현재 상태, 두 번째 원소는 상태를 바꾸어주는 함수
세터(Setter) 함수 : 상태를 바꾸어주는 함수

useState 여러번 사용하기 (Say.js)

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>
    </div>
  );

state를 사용할 때 주의사항

state 값을 바꿀 때는 반드시 setState or useState를 통해 전달받은 세터 함수를 사용하자.

잘못된 코드

this.state.number = this.state.number + 1;
this.state.array = this.array.push(2);
this.state.object.value = 5;

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

state 값이 아닌 배열이나 객체를 업데이트 해야할 때는?

기존의 배열이나 객체 사본을 만들고 사본에 값을 업데이트한다.
그 사본의 상태를 setState 혹은 세터함수를 통해 업데이트 한다.

const object = { a: 1, b: 2, c: 3 };
const nextObject = { ...object, b: 4 };

const array = [
  { id: 1, value: true },
  { id: 2, value: true },
  { id: 3, value: true },
];

let nextArray = array.concat({ id: 4 });
nextArray.filter((item) => item.id !== 2); //id가 2인 항목 제거
nextArray.map((item) => (item.id === 1 ? { ...item, value: false } : item)); //id가 1인 항목의 value를 false로 설정

객체에 대한 사본을 만들 때는 spread 연산자(...)를 사용해서 처리한다.
배열에 대한 사본을 만들 때는 배열의 내장함수들을 활용한다.

0개의 댓글