본문 바로가기

React

[React] 참조형 State/ 주사위 총점 계산 및 기록하기

1. 주사위 총점 계산

 

주사위 총점 계산을 위해 새로운 sumState 를 만듬, 초기값은 0.

 const [sum, setSum] = useState(0);

 

다음과 같이 setSum 에 sum + nextSum 을 하여 총점 계산

    const handleRollClick = () => {
        const nextNum = random(6);
        setNum(nextNum);
        setSum(sum + nextNum);
    };

 

초기화 값은 0 으로 지정.

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

 

2. 주사위 점수 기록

 

주사위 점수 기록을 배열 형태로 다루기 위해 초기값을 빈 배열로 지정.

const [gameHistory, setGameHistory] = useState([]);

 

gameHistory(state) 에 push 메소드로 nextNum (다음주사위점수) 를 추가하고, setGameHistory 에 새로 추가된 gameHistory 값d을 넣어줌.

    const handleRollClick = () => {
        const nextNum = random(6);
        setNum(nextNum);
        setSum(sum + nextNum);
        gameHistory.push(nextNum);
        setGameHistory(gameHistory);
    };

 

setGameHistory([]) 빈 배열을 초기값으로 지정.

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

 

다음과같이 HTML 로 등록함. join 은 각 주사위 숫자값을 쉼표로 연결해주는 메소드

    return (
    <div>
        <div>
            <Button onClick={handleRollClick}>던지기</Button>
            <Button onClick={handleClearClick}>처음부터</Button>
        </div>
        <div>
            <Dice color="blue" num ={num} />
            <h2>총점</h2>
            <p>{sum}</p>
            <h2>기록</h2>
            <p>{gameHistory.join(', ')}</p>  
            {/* join 각 주사위 숫자값들을 쉼표로 연결하여 결과적으로 하나의 문자열로 만들어주는 메소드 */}
        </div>
    </div>
    );

참고, 주석처리방법 : {/* */}

 

이처럼 주사위를 던지면 총점과 점수 기록이 나타남.

 

전체코드

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

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 handleRollClick = () => {
        const nextNum = random(6);
        setNum(nextNum);
        setSum(sum + nextNum);
        gameHistory.push(nextNum);
        setGameHistory(gameHistory);
    };

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


    return (
    <div>
        <div>
            <Button onClick={handleRollClick}>던지기</Button>
            <Button onClick={handleClearClick}>처음부터</Button>
        </div>
        <div>
            <Dice color="blue" num ={num} />
            <h2>총점</h2>
            <p>{sum}</p>
            <h2>기록</h2>
            <p>{gameHistory.join(', ')}</p>  
            {/* join 각 주사위 숫자값들을 쉼표로 연결하여 결과적으로 하나의 문자열로 만들어주는 메소드 */}
        </div>
    </div>
    );
}

export default App;

 

그러나 이 방법은 잘못된 방법임 (열심히 썼는데 잘못된 방법이라니) 

이유는 밑에서 확인

 

 


 

위의 코드에서 주석처리를한 부분을 보면  (주석 단축키 : 드래그 + ctrl + / , 맥북: 드래그 + command + /) 

setNum(주사위던지기)과 setSum(주사위점수 합치기)을 주석처리하면 마찬가지로 기록도 되지 않게 되어버림.

배열은 기본형이 아닌 참조형이기 때문

gameHistory 변수는 배열을 가진 주소값을 가지게 되는 것이므로 state 가 변경되었다고 판단하지 않음.

참조형 타입의 state 를 변경할때는, 전체를 새로 만든다고 생각해야함.

 

따라서, spread 문법을 활용하여 코드를 다음과 같이 바꿔주면됨.

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

 

기록정상 작동함.

'React' 카테고리의 다른 글

[React] CSS 클래스 네임  (0) 2023.03.23
[React] 인라인 스타일  (0) 2023.03.23
[React] State/ 주사위 던지기  (0) 2023.03.18
[React] children  (0) 2023.03.17
[React] Props  (0) 2023.03.17