티스토리 뷰
배열에 새로운 값을 넣을때 push를 사용하는데 리액트에서는 사용하면 안됨!
기존 배열이 바뀌어버리면 바뀐 값을 리액트가 감지할 수 가 없음
> false값이 나와야 렌더함수가 실행될 수 있는데 원본이 바뀌어버리면 렌더함수를 실행할 수가 없음
그래서 기존 배열을 복제해서 사용해야함
const arr = [];
const arr2 = [...arr, 1];
// arr2 = [1]
arr === arr2
> false
숫자야구 class
// NumberBaseball.jsx
import React, { Component } from 'react';
import Try from './Try-class';
function getNumbers() { // 숫자 4개를 겹치지 않게 랜덤하게 뽑는 함수
const candidate = [1, 2, 3, 4, 5, 6, 7, 8, 9];
const array = [];
for (let i = 0; i < 4; i += 1) {
const choosen = candidate.splice(Math.floor(Math.random() * (9 - i)), 1)[0];
array.push(choosen);
}
return array;
};
class NumberBaseball extends Component {
state = {
value: '',
result: '',
answer: getNumbers(),
tries: [],
};
onSubmitForm = (e) => {
e.preventDefault();
if (this.state.value === this.state.answer.join('')) { // 답 맞았으면
this.setState((prevState) => { // 옛날 state로 현재 state를 만들 때 함수 형태로
return {
result: '홈런!',
tries: [...prevState.tries, { try: this.state.value, result: '홈런!' }],
}
});
alert('게임을 다시 시작합니다!'); // 맞았으니 게임 재실행>초기화
this.setState({
value: '',
answer: getNumbers(),
tries: [],
});
} else { // 답 틀렸으면
const answerArray = this.state.value.split('').map((v) => parseInt(v));
let strike = 0;
let ball = 0;
if (this.state.tries.length >= 9) { // 10번 이상 틀렸을 때
this.setState({
result: `10번 넘게 틀려서 실패! 답은 ${this.state.answer.join(',')}였습니다!`,
});
alert('게임을 다시 시작합니다!'); // 기회를 모두 썼으니 게임 재실행>초기화
this.setState({
value: '',
answer: getNumbers(),
tries: [],
});
} else { // 기회가 남았으면
for (let i = 0; i < 4; i += 1) { // 볼, 스트라이크 알려주고
if (answerArray[i] === this.state.answer[i]) {
strike += 1;
} else if (this.state.answer.includes(answerArray[i])) {
ball += 1;
}
}
this.setState((prevState) => { // 기회 더줌
return {
tries: [...prevState.tries, { try: this.state.value, result: `${strike} 스트라이크, ${ball}볼 입니다.` }],
value: '',
}
});
}
}
};
onChangeInput = (e) => {
console.log(this.state.answer, this.state.tries);
this.setState({
value: e.target.value,
});
};
render() {
return (
<>
<h1>{this.state.result}</h1>
<form onSubmit={this.onSubmitForm}>
<input maxLength={4} value={this.state.value} onChange={this.onChangeInput} />
</form>
<div>시도: {this.state.tries.length}</div>
<ul>
{this.state.tries.map((v, i) => { // v는 객체 > {try: this.state.value, result: `${strike} 스트라이크, ${ball}볼 입니다.`}
return (
<Try key={`${i + 1}차 시도:`} tryInfo={v} />
); // props로 전달
})}
</ul>
</>
);
}
}
export default NumberBaseball;
// Try.jsx
import React, { Component } from 'react';
class Try extends Component {
render() {
return (
<li>
<div>{this.props.tryInfo.try}</div>
<div>{this.props.tryInfo.result}</div>
</li>
)
}
}
export default Try;
this.state를 생략하는 방법
비구조화 할당으로 간단하게 만들 수 있음
render() {
const { result, value, tries } = this.state;
return (
<>
<h1>{result}</h1>
<form onSubmit={this.onSubmitForm}>
<input maxLength={4} value={value} onChange={this.onChangeInput}/>
</form>
<div>시도: {tries.length}</div>
<ul>
{tries.map( (v, i) => { // v는 객체 > {try: this.state.value, result: `${strike} 스트라이크, ${ball}볼 입니다.`}
return (
<Try key={`${i+1}차 시도:`} tryInfo={v}/>
); // props로 전달
})}
</ul>
</>
);
}
내가 만든 함수 안에서도 이렇게 선언하고 줄일수 있음
this를 안쓰는 경우 컴포넌트 밖으로 뺄 수 있음 - getNumbers() 같은 경우!
> 그럼 다른데서도 쓸 수 있음
hooks로 바꿀 때도 영향을 받지 않음
숫자야구 hooks
// NumberBaseBall.jsx
import React, { useState } from 'react';
import Try from './Try';
function getNumbers() {
const candidate = [1, 2, 3, 4, 5, 6, 7, 8, 9];
const array = [];
for (let i = 0; i < 4; i += 1) {
const choosen = candidate.splice(Math.floor(Math.random() * (9 - i)), 1)[0];
array.push(choosen);
}
return array;
};
const NumberBaseball = () => {
const [result, setResult] = useState('');
const [value, setValue] = useState('');
const [answer, setAnswer] = useState(getNumbers());
const [tries, setTries] = useState([]);
const onSubmitForm = (e) => {
e.preventDefault();
if (value === answer.join('')) {
setResult('홈런!');
setTries((prevTries) =>
[...prevTries, { try: value, result: '홈런!' }]
);
alert('게임을 다시 시작합니다!');
setValue('');
setAnswer(getNumbers());
setTries([]);
} else {
const answerArray = value.split('').map((v) => parseInt(v));
let strike = 0;
let ball = 0;
if (tries.length >= 9) {
setResult(`10번 넘게 틀려서 실패! 답은 ${answer.join(',')}였습니다!`,);
alert('게임을 다시 시작합니다!');
setValue('');
setAnswer(getNumbers());
setTries([]);
} else {
for (let i = 0; i < 4; i += 1) {
if (answerArray[i] === answer[i]) {
strike += 1;
} else if (answer.includes(answerArray[i])) {
ball += 1;
}
}
setTries((prevTries) =>
[...prevTries, { try: value, result: `${strike} 스트라이크, ${ball}볼 입니다.` }]
);
setValue('');
}
}
};
const onChangeInput = (e) => {
setValue(e.target.value);
};
return (
<>
<h1>{result}</h1>
<form onSubmit={onSubmitForm}>
<input maxLength={4} value={value} onChange={onChangeInput} />
</form>
<div>시도: {tries.length}</div>
<ul>
{tries.map((v, i) => {
return (
<Try key={`${i + 1}차 시도:`} tryInfo={v} />
);
})}
</ul>
</>
);
}
export default NumberBaseball;
// Try.jsx
import React from 'react';
const Try = ({ tryInfo }) => {
return (
<li>
<div>{tryInfo.try}</div>
<div>{tryInfo.result}</div>
</li>
)
};
export default Try;
728x90
'유튜브 강의' 카테고리의 다른 글
제로초 리액트 강의 3.5 (0) | 2021.11.09 |
---|---|
제로초 리액트 강의 3.4 리렌더링 방지, createRef (0) | 2021.11.09 |
제로초 리액트 강의 3.2 (0) | 2021.11.08 |
제로초 리액트 강의 3.1 map (0) | 2021.11.04 |
제로초 리액트 강의 2.2 (0) | 2021.11.01 |
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
링크
TAG
- 김버그
- 파이썬
- Python
- 제로초
- 자바스크립트
- Typescript
- 제이쿼리
- 깃
- map
- React
- scss
- 타입스크립트
- 코딩앙마
- TS
- js
- vscode
- 드림코딩
- CSS
- vue
- 코드잇
- 스파르타코딩클럽
- 회고
- 저스트코드
- 비주얼스튜디오코드
- Til
- 리액트
- git
- javascript
- html
- 구름에듀
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
글 보관함