jineecode

state 본문

JS/react

state

지니코딩 2021. 4. 27. 23:08

src/Counter.js

import React, { Component } from "react";

class Counter extends Component {
  constructor(props) {
      super(props);
      this.state = {
          //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;

 

class Counter extends Component {
  constructor(props) {
      super(props);
      this.state = {
          //state의 초깃값 설정하기
          number: 0;
      }
  }

state를 작성할 때 constructor 메서드를 작성하여 설정한다.

클래스형 컴포넌트에서 constructor를 작성할 때는 super(props)를 호출해야 한다.

이 함수가 호출되면 현재 클래스형 컴포넌트가 상속받고 있는 리액트의 Component 클래스가 지닌 생성자 함수를 호출해준다.

 

그 다음에는 this.state 값에 초깃값을 설정한다.

컴포넌트의 state는 객체형식이어야 한다. 

 

state는 이렇게도 쓸 수 있다.

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

//

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

 render 함수에서 현재 state를 조회할 때 this.state를 조회한다.

이벤트로 설정할 함수를 넣어줄 때는 화살표 함수 문법을 사용해서 넣는다.

함수 내부에는 this.setState 함수를 사용하였는데, 이 함수가 state 값을 바꿀 수 있게 한다.

이 의미는 setState를 설정하지 않으면 그 state는 고정이 된다는 뜻이다.

 

import React, { Component } from "react";

class Counter extends Component {
  constructor(props) {
    super(props);
    this.state = {
      //state의 초깃값 설정하기
      number: 0,
      fixedNumber: 0,
    };
  }

  render() {
    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;

 

setState를 두 번 쓰면 2 씩 올라갈까?

 

 

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={() => {
            this.setState({ number: number + 1 });
            this.setState({ number: this.state.number + 1 });
          }}
        >
          +1
        </button>
      </div>
    );
  }
}

export default Counter;

 

setState를 사용한다고 해서 state 값이 바로 바뀌지는 않기 때문에 1씩 더해진다.

 

setState를 사용할 때 객체 대신에 함수를 인자로 넣어주어서 바꿔주자.

this.setState((prevState, props)=> {
	return {
    
    }
})

prevState : 기존 상태

props: 현재 지니고 있는 props

 

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={() => {
            this.setState((prevState) => {
              return {
                number: prevState.number + 1,
              };
            });
            // 위와 아래 코드는 같은 기능을 한다.
            this.setState((prevState) => ({
              number: prevState.number + 1,
            }));
          }}
        >
          +1
        </button>
      </div>
    );
  }
}

export default Counter;

 화살표 함수에서 값을 바로 반환하고 싶다면 { } 을 생략하면 된다.

const sum = (a, b) => a + b;

return 이 { } 였다고 생각하면 쉽다.

 

setState의 두 번째 파라미터로는 콜백을 수행할 수 있다.

 

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={() => {
            this.setState(
              {
                number: number + 1,
              },
              () => {
                console.log("방금 setState가 호출되었습니다.");
                console.log(this.state);
              }
            );
          }}
        >
          +1
        </button>
      </div>
    );
  }
}

export default Counter;

 

배열 비구조화 할당

객체 비구조화 할당처럼, 배열도 비구조화 할당을 할 수 있다.

ES6 :

destructuring

  var [a, b] = [10, 100];
  var a = 10
  var b = 100

 

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

....위와 아래는 같다...

const array [1, 2];
const [one, tow] = array;

useState를 쓰게 되면 두 개의 자리가 있는 배열이 하나 생성된다.

[현재상태, 현재 상태를 바꾸어주는 함수]

 

ES6문법인 destructuring을 이용하여 

좌우 배열을 맞추어 써주면 useState를 쓸 준비가 된다.

  const [message, setMessage] = useState("");

 

함수형 컴포넌트에서 state를 사용하는 방법은, useState 함수를 사용하면 가능하다.

 

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;

import React, { useState } from "react";

리액트에 있는 useState라는 내장함수를 쓰겠다는 뜻

 

state는 객체 형태로 넣어주어야 하지만 useState는 객체가 아니어도 상관없다.

함수를 호출하게 되면, 배열의 첫번째 원소는 현재 상태이고, 두 번째 원소는 상태를 바꾸어주는 함수이다.

이를 Setter 함수라고 한다.

 

useState의 두 번째 원소는, 기존의 state에 있는 값을 모두 갈아버린다. 등호를 쓰거나 특정 한 부분만 바꾸지 않고 모두 바꾸어준다.

 

useState는 여러 번 쓸 수 있다.

 

import React, { 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;

 


import React, { useState } from "react";
import logo from "./logo.svg";
import "./App.css";

function App() {
  let posts = "데이터바인딩";

  let [글제목, 글제목변경] = useState("오늘 한 일");
  return (
    <div className="App">
      <div className="black-nav">
        <div>개발 Blog</div>
      </div>
      <h4>{posts}</h4>
      <div className="boardList">
        <h3>{글제목}</h3>
        <p>2월 17일 발행</p>
        <hr />
      </div>
      <div className="boardList">
        <h3>{posts}</h3>
        <p>2월 17일 발행</p>
        <hr />
      </div>
      <div className="boardList">
        <h3>{posts}</h3>
        <p>2월 17일 발행</p>
        <hr />
      </div>
    </div>
  );
}

export default App;

 

 

배열 형식으로 넣어도 아무런 문제가 없다.

import React, { useState } from "react";
import logo from "./logo.svg";
import "./App.css";

function App() {
  let posts = "데이터바인딩";

  let [글제목, 글제목변경] = useState(["오늘 한 일", "내일 할 일"]);
  return (
    <div className="App">
      <div className="black-nav">
        <div>개발 Blog</div>
      </div>
      <h4>{posts}</h4>
      <div className="boardList">
        <h3>{글제목[0]}</h3>
        <p>2월 17일 발행</p>
        <hr />
      </div>
      <div className="boardList">
        <h3>{글제목[1]}</h3>
        <p>2월 17일 발행</p>
        <hr />
      </div>
      <div className="boardList">
        <h3>{posts}</h3>
        <p>2월 17일 발행</p>
        <hr />
      </div>
    </div>
  );
}

export default App;

 

 

그렇다면 왜 변수로 담아 사용하지 않고 state를 사용할까?

 

변수에 담아서 사용하면, 만약 글 제목이 바뀐다면 변수에 담았던 텍스트를 일일이 수정해야하며 새로고침을 해야 렌더링이 되는데 state를 사용하면 데이터를 담고있는 HTML이 자동으로 재렌더링된다.

 

즉, 자주 바뀌고 중요한 데이터는 state로 관리하는 게 좋다.

 


useState의 두 번째 파라미터를 이용하여 state를 변경할 때의 스킬

 

어떤 버튼이 있다.

  let [title, changeTitle] = useState([
    "오늘 한 일",
    "내일 할 일",
    "모레 할 일",
  ]);
  
  function changeTitleFunction() {
    changeTitle(["안녕", "내일 할 일", "모레 할 일"]);
  }


<button onClick={changeTitleFunction}>바뀌는 제목</button>

첫 번째만 '안녕'으로 바꾸고 싶을 때:

 

버튼을 누르면

changeTitleFunction() 가 실행이 되고,

useState의 두 번째 파라미터(changeTitle)에 따라, 오늘 한 일안녕으로 바뀌게 된다.

 

하지만 배열에 담긴 데이터가 무수하다면?

 

이럴 때 특정 하나의 데이터만 바꿀 수 있는 방법이 있다.

 

리액트의 immutable data 에 따라 state를 직접 바꾸진 못하지만 state에 담긴 데이터를 '복사'하여 바꿀 수는 있다.

 

 

ES6 spread operator deep copy 문법:

[...] 혹은 {...}

 

값 공유가 일어나지 않고 완전히 별개의 새로운 복사본.

 

... : 중괄호, 대괄호 다 없애주세요

{...} : 중괄호, 대괄호 다 없앤 뒤 다시 중괄호를 만든 새로운 복사본

 

 

 

 

 

 

 

 

 

'JS > react' 카테고리의 다른 글

이벤트에 따른 class명 변경  (0) 2021.04.29
이벤트 핸들링  (0) 2021.04.29
props  (0) 2021.04.27
궁금증 해소  (0) 2021.04.27
componentDidMount() 응용.  (0) 2021.02.11
Comments