● Defalut 상황
○ Dicegame 프로젝트에서, useState()메소드를 이용하여, 돌렸을 때마다, " 총점 , 기록 " 을 하는 항목 추가해보기
- App.js :
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 handleRollClick = () => {
const nextNum = random(6);
setNum(nextNum);
};
const handleClearClick = () => {
setNum(1);
};
return (
<div>
<div>
<Button onClick={handleRollClick}>던지기</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;
● 먼저 그냥 무근본이라도 작성해보기 :
import { useState } from 'react'; //useState 를 react 컴ㅍ넌트에서 불러오기
import Button from './Button';
import Dice from './Dice';
function App() {
const [num, setNum] = useState(1);
const [sum, setSum] = useState(0); //sum에 해당 useState 초기화
const [Record, setRecord] = useState([]); //기록에 해당 배열 useState 초기화
//onClick용 함수
const handleRollClick = ()=>{
const randNum = Math.floor(Math.random()*(6-0)) +1;
setNum(randNum);//num을 3으로 변경해주는 메소드
setSum(sum + randNum);//sum (초기 0) + 나온 randNum 값 추가
Record.push(randNum);//던진 후, 나온 눈값 randNum을 배열에 push
setRecord(Record);//배열 업데이트
};
//onClick 처음부터 메소드
const setReset = ()=>{
setNum(1);//num을 3으로 변경해주는 메소드
setSum(0);//초기화 => 0값
setRecord([]);//초기화 => 빈 배열
};
return (
//.Array프로퍼티 메소드 join(', ')메소드를 이용하여, 배열에 원소 출력
<>
<div>
<Button onClick={handleRollClick}>던지기</Button>
<Button onClick={setReset}>처음부터</Button>
</div>
<Dice color="blue" num={num} />
<p>총점 : {sum}</p>
<p>기록 : {Record.join(', ')}</p>
</>
)
}
export default App;
○ 출력 장면 :
● 알아야 할 개념 :
- 개념1_ 기본자료형 vs 참조자료형 차이
- 기본 자료형 : 숫자 , 문자, bool
- 참조 자료형 : Array, String , Date
예를 들어, 아래와 같이, 변수 선언 후, C언어에서 출력시
#include <stdio.h>
int main(){
int var = 3;
int arr = [1,3,4,5];
printf("변수 : %d \n",var);//변수값이 출력된다.
printf("배열 : %d \n",arr);//★인덱스0의 주소가 출력된다.
return 0;
}
내 생각엔 저 위의 원리가 적용되는 거 같다.
- 개념2_ const [업데이트할 변수, set어쩌구메소드()] = useState(초기값);
업데이트할 변수 가 기본자료형 ,참조자료형에 따라 다르게 인식하게 된다.
● 그래서, 어떤 문제가 발생? => "총점은 ㅈ까고, 기록만 하고 싶을 때, 문제 발생"
import { useState } from 'react'; //useState 를 react 컴ㅍ넌트에서 불러오기
import Button from './Button';
import Dice from './Dice';
function App() {
const [num, setNum] = useState(1);
const [Record, setRecord] = useState([]); //기록에 해당 배열 useState 초기화
//onClick용 함수
const handleRollClick = ()=>{
const randNum = Math.floor(Math.random()*(6-0)) +1;
Record.push(randNum);//던진 후, 나온 눈값 randNum을 배열에 push
setRecord(Record);//배열 업데이트
console.log(Record);
};
//onClick 처음부터 메소드
const setReset = ()=>{
setNum(1);//num을 3으로 변경해주는 메소드
setRecord([]);//초기화 => 빈 배열
};
return (
//.Array프로퍼티 메소드 join(', ')메소드를 이용하여, 배열에 원소 출력
<>
<div>
<Button onClick={handleRollClick}>던지기</Button>
<Button onClick={setReset}>처음부터</Button>
</div>
<Dice color="blue" num={num} />
<p>기록 : {Record.join(', ')}</p>
</>
)
}
export default App;
○ 출력장면 :
=> 버튼을 계속 누를시 ,배열에 계속 추가되는 것은 console창에서 보면, 알수있지만, useState는 첫번째 인덱스의 원소||주소만 바꼈는지만 확인하여, ㅄ이 업데이트됐다고 생각안하고, 기록을 안함
● 해결방법 :
- 초기화 단계는 그대로
- onClick 메소드 작성시,
배열.push() 후, setRecord([...객체변수이름, 추가할 값])를 thread 문법으로 한다.
import { useState } from 'react'; //useState 를 react 컴ㅍ넌트에서 불러오기
import Button from './Button';
import Dice from './Dice';
function App() {
const [num, setNum] = useState(1);
const [Record, setRecord] = useState([]); //기록에 해당 배열 useState 초기화
//onClick용 함수
const handleRollClick = ()=>{
const randNum = Math.floor(Math.random()*(6-0)) +1;
setNum(randNum);
setRecord([...Record,randNum]);//배열 업데이트
};
//onClick 처음부터 메소드
const setReset = ()=>{
setNum(1);//num을 3으로 변경해주는 메소드
setRecord([]);//초기화 => 빈 배열
};
return (
//.Array프로퍼티 메소드 join(', ')메소드를 이용하여, 배열에 원소 출력
<>
<div>
<Button onClick={handleRollClick}>던지기</Button>
<Button onClick={setReset}>처음부터</Button>
</div>
<Dice color="blue" num={num} />
<p>기록 : {Record.join(', ')}</p>
</>
)
}
export default App;
◎ 연습문제 :
주어진 getResult 함수를 사용해서 승리, 패배, 무승부에 해당하는 승부 결과를 만들 수 있었는데요.
이번 레슨에서는 이걸 누적해서 보여주는 승부 기록을 만들어 봅시다.
아래를 참고해서 App.js 파일을 수정해 주세요.
- ○ handleButtonClick 함수에서 gameHistory state에 nextHistoryItem 을 새 요소로 추가해 주세요.
- ○ handleClearClick 함수에서는 gameHistory 를 빈 배열로 변경합니다.
=> 답 :
function App() {
const [hand, setHand] = useState(INITIAL_VALUE);
const [otherHand, setOtherHand] = useState(INITIAL_VALUE);
const [gameHistory, setGameHistory] = useState([]);
const handleButtonClick = (nextHand) => {
const nextOtherHand = generateRandomHand();
const nextHistoryItem = getResult(nextHand, nextOtherHand);
//setHand(nextHand);
//setOtherHand(nextOtherHand);
// gameHistory에 nextHistoryItem 을 추가해 주세요
setGameHistory([...gameHistory,getResult()]);
};
const handleClearClick = () => {
setHand(INITIAL_VALUE);
setOtherHand(INITIAL_VALUE);
// gameHistory를 비워주세요
setGameHistory([]);
};
return (
<div>
<Button onClick={handleClearClick}>처음부터</Button>
<div>
<HandIcon value={hand} />
VS
<HandIcon value={otherHand} />
</div>
<p>승부 기록: {gameHistory.join(', ')}</p>
<div>
<HandButton value="rock" onClick={handleButtonClick} />
<HandButton value="scissor" onClick={handleButtonClick} />
<HandButton value="paper" onClick={handleButtonClick} />
</div>
</div>
);
}
'CodeIt_Sprint > React_초급' 카테고리의 다른 글
(11)React_초급_ 컴포넌트 재사용 하기(작성중) (0) | 2024.11.23 |
---|---|
(10)React_초급_ useState() 실습문제 (0) | 2024.11.23 |
(9)React_초급_JSX 문법6 : props객체의 Children 프로퍼티, useState 사용하기 (0) | 2024.11.23 |
(8)React_초급_JSX 문법5 : 컴포넌트 속성지 (0) | 2024.11.22 |
(7)React_초급_JSX 문법4 : 커스텀 태그 만들기, 컴포넌트 만들기 (0) | 2024.11.21 |