개발새발개발/React

React state, 클래스형 컴포넌트와 함수형 컴포넌트에서의 state와 주의사항

birdsfoot 2024. 12. 25.

 

 

state

  • 컴포넌트 내부에서 바뀔 수 있는 값

 

클래스형 컴포넌트의 state


 

 

컴포넌트에 state 설정하기 :  constructor 메서드 사용

class Counter extends Component {
  constructor(props) {
    super(props);
    //state의 초기값 설정하기
    this.state = {
      number: 0,
    };
  }
  • 반드시 super(props)를 함께 호출해야 한다
  • this.state 를 사용해 초기값을 설정한다

 

render

  render() {
    const { number } = this.state; //state를 조회할 때는 this.state로 조회
    return (
      <div>
        <h1>{number}</h1>
        <button
          onClick={() => {
            //state에 새로운 값 넣기: this.setState
            this.setState({ number: number + 1 });
          }}
        >
          +1
        </button>
      </div>
    );
  }

 

  • this. state : 현재 state 조회 
  • button onClick : 버튼이 클릭될 때 호출시킬 함수 설정(화살표 함수 사용)
  • setState : state 값을 바꿔주는 함수

 

전체 코드

//Counter.js

import React, { Component } from 'react';

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

export default Counter;

 

//App.js

import Counter from './Counter';

const App = () => {
  return <Counter />;
};

export default App;

 

 

 

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

 

//Counter.js

import React, { Component } from 'react';

class Counter extends Component {
  constructor(props) {
    super(props);
    //state의 초기값 설정하기
    this.state = {
      number: 0,
      fixedNumber: 0,    // fixedNumber 추가
    };
  }
  render() {
    const { number, fixedNumber } = this.state; // fixedNumber 추가
    return (
      <div>
        <h1>{number}</h1>
        <h2>바뀌지 않는 값 : {fixedNumber}</h2>
        <button
          onClick={() => {
            //state에 새로운 값 넣기: this.setState
            this.setState({ number: number + 1 });   // fixedNumber 추가로 넣지 않음
          }}
        >
          +1
        </button>
      </div>
    );
  }
}

export default Counter;

 

  • this.setState 함수를 사용할 때 인자로 전달되는 개체 내부에 fixedNumber를 넣지 않음
  • => this.setState 함수는 인자로 전달된 객체 안에 있는 값만 바꿔준다

 

 

 

state의 초기값을 지정하는 또다른 방법

  • constructor 없이 state를 사용할 수 있다
//Counter.js

import React, { Component } from 'react';

class Counter extends Component {
  state = {
    number: 0,
    fixedNumber: 0,
  };
  render() {
    const { number, fixedNumber } = this.state;
    return (...);
  }
}

export default Counter;

 

 

 

this.setState에 함수 인자 전달하기

  • this.setState를 사용하여 state 값을 업데이트 할 때는 상태가 비동기적으로 업데이트 된다
  • 숫자를 2씩 올리고 싶을 때
  onClick={() => {
    //state에 새로운 값 넣기: this.setState
    this.setState({ number: number + 1 });
    this.setState({ number: this.state.number + 1 });
  }}
  • this.setState를 쓴다해서 숫자가 바로 업데이트 되지 않기 때문에 숫자가 1씩만 더해진다

 

  • 해결 방법 : 아래와 같이 함수를 인자로 넣어주면 된다
this.setState((prevState,props) => {
  return {
    // 업데이트 하고 싶은 내용
  };
});
  • prevState는 기존 상태를, props는 현재 지니고 있는 props를 의미한다
  • props는 불필요하다면 생략 가능하다

 

<button
  onClick={() => {
    //state에 새로운 값 넣기: this.setState
    this.setState((prevState) => {
      return {
        number: prevState.number + 1,
      };
    });
    this.setState((prevState) => ({
      number: prevState.number + 1,
    }));
  }}
>
  • 위의 두 코드는 표현만 다를 분 완전히 똑같은 기능을 한다
  • return 이 생략된 아래 코드는 함수에서 바로 객체를 반환한다는 의미이다
  • 위와 같이 하면 숫자가 2씩 올라간다

 

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

  • setState의 두번째 파라미터로 콜백 함수를 등록하여 작업을 실행
//Counter.js

import React, { Component } from 'react';

class Counter extends Component {
  state = {
    number: 0,
    fixedNumber: 0,
  };
  render() {
    const { number, fixedNumber } = this.state;
    return (
      <div>
        <h1>{number}</h1>
        <h2>바뀌지 않는 값 : {fixedNumber}</h2>
        <button
          onClick={() => {
            //state에 새로운 값 넣기: this.setState
            this.setState(
              {
                number: number + 1,
              },
              () => {
                console.log('setState 호출');
                console.log(this.state);
              }
            );
          }}
        >
          +1
        </button>
      </div>
    );
  }
}

export default Counter;

 

결과

 

 


 

 

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


배열 비구조화 할당

  • 배열 안에 들어있는 값을 쉽게 추출할 수 있도록 해주는 문법
const arr = [1, 2];
const one = arr[0];
const two = arr[1];

 

  • 배열 비구조화할당 사용
const arr = [1, 2];
const [one, two] = arr;

 

 

useState 사용하기

import { 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 함수의 인자 : 상태의 초깃값 넣기. 값의 형태는 상관없다.
  • 함수를 호출하면 배열이 반환된다
    • 첫번째 원소(message) : 현재 상태
    • 두번째 원소(setMessage) : 상태를 바꿔주는 함수(=세터(Setter)함수)
    • 이름은 자유롭게 정해줘도 된다

 

 

한 컴포넌트에서 useState 여러번 사용하기

  • 한 컴포넌트 내에서 여러번 사용 가능하다
import { useState } from 'react';

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

export default Say;

 

결과

 

  • 버튼에 style없애고 코드만 보면 이런 모양
  const [color, setColor] = useState('black');

  return (
    <div>
      <button onClick={onClickEnter}>입장</button>
      <button onClick={onClickLeave}>퇴장</button>
      <h1 style={{ color }}>{message}</h1>
      <button onClick={() => setColor('red')}>빨간색</button>
      <button onClick={() => setColor('green')}>초록색</button>
      <button onClick={() => setColor('blue')}>파란색</button>
    </div>

 

 

state 사용 시 주의사항

  • 값을 변경할 때에는 setState 또는 useState를 통해 전달받은 세터 함수를 사용해야 한다
  • 배열이나 객체를 업데이트해야 할 때에는 사본을 만들고 그 사본에 값을 업데이트 한 후 사본의 상태를 setState 혹은 세터 함수를 통해 업데이트한다.
  • 객체의 사본을 만들 때에는 spread 연산자라 불리는 `...`을 사용한다
  • 배열의 사본을 만들 때에는 배열의 내장함수를 사용한다
  • 올바른 예시
// 객체
const object = { a: 1, b: 2, c: 3 };
const nextObject = { ...object, b: 2 }; // 사본을 만들어서 b 값만 덮어씀

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

// 새 항목 추가
let nextArray = array.concat({ id: 4 });

// id가 2인 항목 제거
nextArray.filter((item) => item.id !== 2);

// id가 1인 항목의 value를 false로 변경
nextArray.map((item) => (item.id === 1 ? { ...item, value: false } : item));

 

  • 잘못된 사용 예시
import { useState } from 'react';

// 클래스형
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;

'개발새발개발 > React' 카테고리의 다른 글

React - ref  (0) 2024.12.29
React 이벤트 핸들링  (1) 2024.12.28
React 컴포넌트(Component), 화살표 함수, Snippet  (1) 2024.12.24
React JSX 문법과 ESLint, Prettier 적용법  (0) 2024.12.23
React JSX란?  (0) 2024.12.22

댓글