본문 바로가기

react

[코드잇] 리액트 웹 개발 시작하기(4)

1. state

- 리액트에서 state란 상태가 바뀔 때마다 화면에 새롭게 그려내는 방식으로 동작하는 것

- 리액트에서 state를 만들고, state를 바꾸기 위해서는 useState라는 함수를 활용

import { useState } from 'react';

// ...

  const [num, setNum] = useState(1);

// ...

 

 - 디스트럭처링 문법으로 작성 

 - useState 함수가 초깃값을 아규먼트로 받고 그에 따른 실행 결과를 요소 2개를 가진 배열의 형태로 리턴 

 - 첫번째 변수는 원하는 state의 이름을 지어줌

 - 두번째 변수는 state 이름앞에 set을 붙인 다음 카멜케이스로 이름을 지어주는 것이 일반적

 

- state는 변수에 새로운 값을 할당하는 방식으로 변경하는 것이 아니라 setter 함수를 활용

- setter 함수는 호출할 때 전달하는 아규먼트 값으로 state 값을 변경해줌

- setter 함수를 활용해서 이벤트 핸들러를 등록해두면, 이벤트가 발생할 때마다 상태가 변하면서 화면이 새로 그려짐 

 

App.js

import { useState } from 'react';
import Dice from './Dice';
import Button from './Button';

function random(n) {
  return Math.ceil(Math.random()*n);
}

function App() {
  const [num, setNum] = useState(1);

  const handleRollClcik = () => {
    const nextNum = random(6);
    setNum(nextNum);
  };

  const handleClearClick = () => {
    setNum(1);
  };

  return (
    <div>
      <Button onClick={handleRollClcik}>던지기</Button>
      <Button onClick={handleClearClick}>처음부터</Button>
      <Dice color ="red" num = {num} />
    </div>
  );
}

export default App;

Button.js

function Button({ children,onClick }) {
  return <button onClick={onClick}>{children}</button>;
}

export default Button;

 

 

 

2. 참조형 state

- 배열 값을 가진 gameHistory의 state는 배열 값 자체를 가지고 있는 게 아니라 그 배열의 주솟값을 참조

- push 메소드로 배열 안에 요소를 변경했다고 하더라도 결과적으로 참조하는 배열의 주솟값은 변경된 것이 아니게 됨 

- 리액트 입장에서는 gameHistory state가 참조하는 주솟값은 여전히 똑같기 때문에 상태(state)가 바뀌었다고 판단 안함

- 참조형 state를 활용할 때는 반드시 새로운 참조형 값을 만들어 state를 변경 해야 함

 -> Spread 문법(...) 활용

 

App.js

import { useState } from 'react';
import Dice from './Dice';
import Button from './Button';

function random(n) {
  return Math.ceil(Math.random()*n);
}

function App() {
  const [num, setNum] = useState(1);
  const [sum, setSum] = useState(0);
  const [gameHistory, setGameHistory] = useState([]);

  const handleRollClcik = () => {
    const nextNum = random(6);
    setNum(nextNum);
    setSum(sum + nextNum);
    setGameHistory([...gameHistory,nextNum]);
  };

  const handleClearClick = () => {
    setNum(1);
    setSum(0);
    setGameHistory([]);
  };

  return (
    <div>
      <div>
      <Button onClick={handleRollClcik}>던지기</Button>
      <Button onClick={handleClearClick}>처음부터</Button>
    </div>
    <div>
      <h2>나</h2>
      <Dice color='blue' num ={num} />
      <h2>총점</h2>
      <p>{sum}</p>
      <h2>기록</h2>
      {gameHistory.join(',')}
    </div>
  </div>
  );
}

export default App;