props와 state의 차이점을 알아보고 두 개념을 이용해서 컴퓨터와 경쟁하는 주사위 게임을 만들다.
1. props와 state 차이점
props는 부모컴포넌트에서 자식컴포넌트로 데이터를 객체형태로 보낼 때 사용한다. 하지만 props는 수정이 불가하고 각 자식 컴포넌트에서 고정된 채로 사용된다. props를 자식컴포넌트에서 변경하고 싶으면 state를 사용해서 변경해서 사용해야한다.
그림 2는 일반적으로 props와 state가 사용되는 흐름을 나타낸 것이다. 부모 컴포넌트에게서 props를 받고 그것을 state로 자식 컴포넌트에서 필요한 데이터로 변경해서 사용한다. props와 state개념을 사용해서 컴퓨터와 내 주사위 중 값이 큰 것이 나온 쪽이 이기는 게임을 만들어 보겠다.
2. 실습
전체 코드 : 부모 컴포넌트(App.js = Ex03.js)
// Ex03.js
import React, { useState } from 'react'
import Board from './components/Board'
import { Button } from 'react-bootstrap';
import 'bootstrap/dist/css/bootstrap.min.css';
import "./style/ex03.css"
// react는 public 폴더에 이미지 경로를 자동으로 public으로 맞춰준다
// public안의 어떤 폴더 안에있는지 무슨파일인지 작성만 하면 된다
/*
실습문제) 주사위 게임 페이지 구현
STEP1) 사용자가 "던지기" 버튼을 누른다.
STEP2) 주사위 눈이 랜덤으로 표시된다.
- 랜덤숫자를 이용해서 이미지 띄우기
STEP3) 사용자의 주사위 눈과 컴퓨터의 주사위 눈을 비교한다.
- 무승부 : alert( )를 활용하여 "무승부" 띄우기
- 사용자 승리 : 사용자 카운트 +1
- 컴퓨터 승리 : 컴퓨터 카운트 +1
STEP4) "Reset" 버튼 클릭 시 모든 내용 초기화
- 점수, 이미지
만들어야 할 state
- 점수
- 주사위 숫자
- 주사위 이미지 경로
만들어야 할 컴포넌트
- Board.jsx
*/
const Ex03 = () => {
const [myDice, mySet] = useState(1)
const [comDice, comSet] = useState(1)
const [myScore, setMyscore] = useState(0)
const [comScore, setComscore] = useState(0)
const handleDice = () => {
let myNumber = Math.floor(Math.random()*6 + 1)
let comNumber = Math.floor(Math.random()*6 + 1)
mySet(myNumber)
comSet(comNumber)
if(myNumber > comNumber){
setMyscore(myScore + 1)
}
else if (myNumber < comNumber){
setComscore(comScore + 1)
}
else if (myNumber == comNumber){
alert("무승부")
}
}
const reset = () => {
mySet(1)
comSet(1)
setMyscore(0)
setComscore(0)
}
return (
<div className='container'>
<div className='button-area'>
<Button onClick={handleDice}>던지기</Button>
<Button onClick={reset}>Reset</Button>
</div>
<div className='board-area'>
<Board name="나" dice={myDice} score = {myScore}/>
<Board name="컴퓨터" comdice={comDice} comScore = {comScore}/>
</div>
</div>
)
}
export default Ex03
사용자는 던지기 버튼을 누르면 나의 주사위 이미지와 컴퓨터의 이미지가 랜덤으로 바뀐다. 그 때 숫자가 더 큰 쪽이 승리하며 점수가 1 증가한다. 무승부이면 alert 창이 뜬다. 던지기 버튼에 onClick으로 클릭했을 때 실행될 함수를 만들었다.
눌렀을 때 나의 랜덤수와 컴퓨터의 랜덤수가 만들어져야 한다. 그리고 해당 랜덤수에 맞춰서 주사위의 이미지도 바뀌어야 한다. 주사위 이미지는 수에 따라 바뀌기 때문에 랜덤수를 사용해서 이미지 파일을 불러오면 된다. 따라서 주사위 이미지는 컴포넌트 내에서 변하는 데이터이기 때문에 state로 관리를 해야한다. 그리고 두 랜덤수를 비교해서 더 큰 쪽의 점수도 1 증가하여 변하기 때문에 컴포넌트의 점수도 state로 관리를 해야한다.
- 주사위 수에 맞는 주사위 이미지 = 주사위 수
- 점수
따라서 랜덤수로 만들어진 각각의 주사위 수를 state 변수로 데이터가 던지기 버튼을 누를 때마다 변하게 해주고, state 변수를 props로 Board 컴포넌트로 보낸다.
전체 코드 : 자식 컴포넌트(Board.jsx)
const Board = ({name, dice, comdice, score, comScore}) => {
let dice1 = dice !== undefined ? dice : comdice
console.log(dice1);
let $dice = `img/dice${dice1}.png`
let $score = score !== undefined ? score : comScore
return (
<div>
<h4>{name}</h4>
<img src={$dice} alt="" />
<div className='score-area'>
<h4>현재 점수는?</h4>
<h4>{$score}</h4>
</div>
</div>
)
}
export default Board
props로 받은 name 변수는 변하지 않으니 그대로 표현식에 넣어준다. 나는 하나의 컴포넌트로 2개의 부분에 서로 다르게 값이 변화하게 하기위해 처음엔 부모 컴포넌트에서 삼항연산자로 태그 자체를 만들었는데 잘못된 접근이었다. 삼항연산자가 서버를 실행하자마자 계속 무한반복되서 에러가 났다. 그래서 일단 자식 컴포넌트로 모두 보내고, 나의 Board에선 computer와 관련된 state 변수는 props로 보내지않아서 오지 않기 때문에 undefined이 뜨기 때문에 그것을 이용해서 각 Board의 변하는 부분을 관리해주었다.
'Front-End > React.js' 카테고리의 다른 글
[React.js] Filter 함수 (0) | 2023.08.29 |
---|---|
[React.js] map 함수 / 컴포넌트 응용 (0) | 2023.08.28 |
[React.js] state (0) | 2023.08.24 |
[React.js] 컴포넌트(Component) (0) | 2023.08.22 |
[React.js] JSX 문법 실습 (0) | 2023.08.21 |