[React] State 상태

MINEW·2022년 7월 8일
0

State 상태

1. useState(기본값)

  • setState는 전후비교로 리렌더링(업데이트) 되기때문에, state 원본을 훼손해서는 안된다!!
  • 기본 예시
// <!-- Counter.js --> 자식 컴포넌트
import React, { useState } from 'react'; // 1번) { useState }는 배열을 리턴한다. 2가지 값이 들어있다 (state, setState).

function Counter(props) {
  // 2번) state는 관리하고 있는 값, setState는 관리하고 있는 값을 변경할때 쓰는 함수
  // 3번) const [ state, setState ] = useState(state의 초기설정값)

  const [ count, setCount ] = useState(0); // 4번)

  return (
    <div>
      <button onClick={ () => (count = count + 1) }> +1 </button> // 5번) 이렇게 사용하면 X
      <button onClick={ () => setCount(count + 1) }> +1 </button> // 6번) setCount(업데이트 값)
      <br />
      Counter: { count }
    </div>
  );
}

export default Counter;

2. setState(원시타입)

  • 원시타입: 불변성O. 변수에 원시타입의 값을 할당하면, 메모리에 값 자체가 저장된다.
  • setState(업데이트 값)
  • 기본 예시
// <!-- Counter.js --> 자식 컴포넌트
import React, { useState } from 'react';

function Counter(props) {
  const [ count, setCount ] = useState(0); // number 형태
  const [ show, setShow ] = useState(true); // boolean 형태
  const operators = [ "+", "-", "*" ];
  const [ operator, setOperator ] = useState(operators[0]); // string 형태

  return (
    <div>
      <button onClick={ // 4번) 클릭하면
        () => {
          let result;
          if (operator === "+") result = count + 1
          if (operator === "-") result = count - 1
          if (operator === "*") result = count * 1
          // setState(업데이트 값)
          setCount(result); // 5번) count값이 변화
        }
      }>
        { operator } 1 // 3번) operator가 결정되고
      </button>

      <button onClick={ () => setShow(!show) }>Show and Hide</button>

      <button onClick={ // 1번) 클릭
        () => {
          const idx = Math.floor(Math.random() * operators.length); // operators.length가 3일때, 0 <= idx <= 2
          setOperator(operators[idx]); // 2번) operator 값이 바뀜
        }
      }>
        Change Operator
      </button>

      // 6번) 둘다 true일때만, Counter: { count }가 보이게 설정 // 7번) count 값은 클릭시에 계속 변동 가능
      { show && `Counter: ${count}` }
    </div>
  );
}

export default Counter;

3. setState(객체타입)

  • 참조타입(객체타입): 불변성X. 변수에 참조타입의 값을 할당하면, 메모리값이 담긴 주소가 저장된다.
  • state 원본을 훼손하지 않는 방법을 사용해야, 전후비교로 업데이트가 된다.
  • 참조타입은 { ...obj }, [ ...arr ] 이런식으로 복사를 통해 해결해야한다.
  • setState({ ...객체복사, 업데이트 값 })
  • 기본 예시
// <!-- Counter.js --> 자식 컴포넌트
import React, { useState } from 'react';

function Counter(props) {
  const operators = ["+", "-", "*"];

  const [ info, setInfo ] = useState({ // 1번) 객체타입으로 넣고
    count: 0,
    show: true,
    operator: operators[0]
  });

  return (
    <div>
      <button onClick={
        () => {
          let result;
          if (info.operator === "+") result = info.count + 1
          if (info.operator === "-") result = info.count - 1
          if (info.operator === "*") result = info.count * 1
          // 3번) setState({ ...객체복사, 업데이트 값 })
          setInfo({ ...info, count: result }); // 참고) 배열일때도 setInfo([ ...array, 새로추가할 요소 ])
        }
      }>
        { info.operator } 1
      </button>

      <button onClick={ () => setInfo({ ...info, show: !info.show }) }>Show and Hide</button>

      <button onClick={
        () => {
          const idx = Math.floor(Math.random() * operators.length) // operators.length가 3일때, 0 <= idx <= 2
          // setOperator(operators[idx]);
          setInfo({ ...info, operator: operators[idx] }); // 2번) 앞에 객체복사 후, 값을 변경해야 -> 전후비교로 업데이트가 된다
        }
      }>
        Change Operator
      </button>

      // 4번) 둘다 true일때만, Counter: { info.count }가 보이게 설정 // info.count 값은 클릭시에 계속 변동 가능
      { info.show && `Counter: ${info.count}` }
    </div>
  );
}

export default Counter;

4. setState()는 '비동기적'으로 실행된다

  • 이 문제를 해결하려면, 호출할때 setState(() => {})
  • 기본 예시
// <!-- Counter.js --> 자식 컴포넌트
import React, { useState } from "react";

export default function App() {
  const [ number, setNumber ] = useState(1);

  // 1번) 현재의 number를 기반으로 변화하도록. ((업데이트된 number) => 업데이트된 number + 1).
  const add = () => setNumber((number) => number + 1); // 얘는 number + 1 해도된다 // 2번)
  const sub = () => setNumber((number) => number - 1); // 얘는 number - 1 해도된다
  const mul2 = () => setNumber((number) => number * 2); // 얘는 number * 1 해도된다
  const mul2add1 = () => { // 여기서 문제가 생긴다! // 3번)
    mul2();
    add();
  };
  // 4번) 중괄호안에서 { number, number: number * 2, number: number +1 } 이런식으로
  // 5번) number가 3일때 -> number = 3, number = 3 * 2, number = 3 + 1 -> 이 과정을 거쳐서 마지막값인 4가 덮어써버리게 된다!!

  return (
    <div>
      <h1> Number : { number } </h1>
      <div>
        <button onClick={ add }> + 1 </button>
        <button onClick={ sub }> - 1 </button>
        <button onClick={ mul2 }> *2 </button>
        <button onClick={ mul2add1 }> *2 + 1 </button>
      </div>
    </div>
  );
}
profile
JS, TS, React, Vue, Node.js, Express, SQL 공부한 내용을 기록하는 장소입니다

0개의 댓글