티스토리 뷰

front-end/React

리액트 State

이안_ian 2019. 12. 3. 01:11




반응형

State

리액트에서 state는 컴포넌트 내부에서 바뀔 수 있는 값을 의미합니다. props는 컴포넌트가 사용되는 과정에서 부모 컴포넌트가 설정하는 값이며, 컴포넌트 자신은 해당 props를 읽기 전용으로만 사용할 수 있습니다. props를 바꾸려면 부모컴포넌트에서 바꿔줘야 합니다. 리액트에는 두 가지 종류의 state가 있습니다. 하나는 클래스형 컴포넌트가 지니고 있는 state이고, 다른 하나는 함수형 컴포넌트에서 useState라는 함수를 통해 사용하는 state입니다.

클래스형 컴포넌트의 state

새로운 컴포넌트를 만들어 다음과 같이 코드를 작성해 보세요.

import React, { Component } from "react";

class Counter extends Component {
  constructor(props) {
    super(props);
    this.state = {
      number: 0
    };
  }
  render() {
    const { number } = this.state;
    return (
      <div>
        <h1>{number}</h1>
        <button
          onClick={() => {
            this.setState({ number: number + 1 });
          }}
        >
          +1
        </button>
      </div>
    );
  }
}

export default Counter;

constructor는 컴포넌트의 생성자 메서드인데요. 클래스형 컴포넌트에서 constructor를 작성할 때는 반드시 super(props)를 호출해 주어야 합니다. 이 함수가 호출되면 현재 클래스형 컴포넌트가 상속하고 있는 리액트의 Component클래스가 지닌 생성자 함수를 호출해 줍니다. 그 다음에는 this.state 값에 초깃값을 설정해 주었습니다. 컴포넌트의 state는 객체 형식이어야 합니다.

 

render함수에서 현재 stateㄹ르 조회할 때는 this.state를 조회하면 됩니다. 그리고 버튼안에 onClick이라는 값을 props로 넣어주었는데요, 이는 버튼이 클릭될 때 호출시킬 함수를 설정할 수 있습니다. 이벤트로 설정할 함수를 넣어줄 때는 화살표 함수 문법을 사용해야합니다. 이제 랜더링해 봅시다.

import React from "react";
import Counter from "./Counter";

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

export default App;

state를 constructor에서 꺼내기

좀더 간편하게 초깃값 설정을 해봅시다.

class Counter extends Component {
  state = {
    number: 0,
    fixedNumber: 0
  };
  render() {
    const { number,fixedNumber } = this.state;
    return (
      <div>
        <h1>{number}</h1>
        <button
          onClick={() => {
            this.setState({ number: number + 1 });
          }}
        >
          +1
        </button>
      </div>
    );
  }
}

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

this.setState를 사용하여 state값을 업데이트할 때는 상태가 비동기적으로 업데이트됩니다. 만약 다음과 같이 onClick에 설정한 함수 내부에서 this.setState를 두 번 호출하면 어떻게 될까요?

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

이렇게 해도 값은 2씩 증가하지않고 1씩 증가합니다. this.setState를 사용한다고 해서 state값이 바로 바뀌지는 않기 때문입니다. 이에 대한 해결책은 객체 대신 함수를 인자로 넣어주는 겁니다. 코드를 다음과 같이 수정해 봅시다.

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

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

setState를 사용하여 값을 업데이트하고 난 뒤 특정 작업을 하고 싶을 때는 setState의 두 번째 파라미터로 콜백(callback)함수를 등록하여 작업을 처리할 수 있습니다.

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

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

원래 함수형 컴포넌트에서는 stateㄹ르 사용할 수 없었지만 16.8 이후부터 useState라는 함수를 사용하여 함수형 컴포넌트에서도 state를 사용할 수 있게 되었습니다. 사용법은 조금 다릅니다. 이 과정에 Hooks를 사용하게 됩니다.

 

배열 비구조화 할당 문법을 알고나면 useState 사용 방법을 쉽게 이해할 수 있습니다. 새 컴포넌트를 만들어서 useState를 사용해 보겠습니다. src디렉터리에 say.js라는 파일을 생성하고 다음 코드를 작성해보시요.

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

export default Say;

 useState 함수의 인자에는 상태의 초깃값을 넣어 줍니다. 클래스형 컴포넌트에서의 state 초기값은 객체 형태를 넣어 주어야 한다고 배웠는데요. useState에서는 반드시 객체가 아니어도 상관없습니다. 값의 형태는 자유입니다. 숫자일 수도, 문자열 일수도, 객체일 수도 있습니다. 함수를 호출하면 배열이 반환되는데 배열의 첫 번째 원소는 현재 상태이고, 두 번째 원소는 상태를 바꾸어 주는 함수 입니다. 이 함수를 세터라 부릅니다. 그리고 배열 비구조화 할당을 통해 이름을 자유롭게 정해 줄 수 있습니다.

state를 사용할 때 주의사항

state를 사용할 때는 주의해야할 점이 있습니다. state의 값을 바꿀 때는 setState 혹은 useState를 통해 전달받은 세터 함수를 사용해야합니다. 예들들어 다음과 같은 코드는 잘못된 코드입니다.

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

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

그렇다면 배열이나 객체를 업데이트할 때는 어떻게 해야할까? 이런 상황에서는 배열이나 객체의 사본을 만들고 그 사본에 값을 업데이트 한 후 그 사본의 상태를 setState 통해 업데이트 합니다.

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}); //새 항목 추가
nextArray.filter(item => item.id !==2); //id가 2인 항목제거
nextArray.map(item => (item.id ===1 ? {...item, value: false}: item)); //id가 1인 항목의 value를 false로 지정

 

 

출처: 리액트를 다루는 기술

 

 

 

반응형

'front-end > React' 카테고리의 다른 글

리액트 ref  (0) 2019.12.05
리액트 이벤트 조작([e.target.name] : e.target.value)  (0) 2019.12.04
리액트 컴포넌트와 props  (0) 2019.12.03
리액트 JSX 문법  (0) 2019.12.01
리액트 코드 이해하기  (0) 2019.11.30
댓글
반응형
최근에 달린 댓글
글 보관함
Total
Today
Yesterday
최근에 올라온 글
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31