리액트에서는 push를 사용하지 않는다.
리액트에서는 뭐가 바꼈는지 감지를 하지 못한다.( = 랜더하지말아야지가 된다)
-> 스프레드 연산자를 사용한다.
구조분해 문법으로 this.state 나 this.props중복을 없앨 수 있음.
const { result, value, tries } = this.state;
return (
<>
<h1>{result}</h1> // this.state.result인데 this.state 생략가능
getNumbers() 를 밖에 사용하는 이유 : 혹시나 다른 곳에서 사용하기 위하여, 훅스로 바꿔도 영향 받지 않음.
redux, mobx를 사용하는 것이 깔끔하다. 부모와 자식간의 관계를 알기 위하여
map은 1:1로 짝짓는 것이다.
개발 모드를 배포 모드를 바꾸려면, production으로 바꾸고, 맨위에 process.env.NODE_ENV = 'production' 을 추가.
훅스
// hooks
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 chosen = candidate.splice(Math.floor(Math.random() * (9 - i)), 1)[0];
array.push(chosen);
}
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) => {
return [...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) => {
return [...prevTries, {try: value, result: `${strike} 스트라이크, ${ball} 볼 입니다.`}]
});
setValue('');
}
}
};
const onChangeInput = (e) => {
console.log(answer);
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} />
); // return 생략가능
})}
</ul>
</>
)
}
클래스형
class NumberBaseball extends Component {
state = {
result: '',
value: '',
answer: getNumbers(), // ex: [1,3,5,7]
tries: [],
};
onSubmitForm = (e) => {
e.preventDefault();
if (this.state.value === this.state.answer.join('')) {
this.setState( (prevState) => {
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) {
this.setState({
result: `10번 넘게틀려서 실패! 답은 ${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.setState({
value: e.target.value,
})
};
render() {
const { result, value, tries } = this.state;
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) => {
return (
<Try key={`${i + 1}차 시도 :`} tryInfo={v} />
); // return 생략가능
})}
</ul>
</>
)
}
}
state, props가 바뀌어야만 렌더링이 된다.
setState만 호출하면 렌더링이 다시 일어남.
이럴때
shouldComponentUpdate 를 사용한다. (react에서 제공하는 메소드)
어떤 경우에만 렌더링을 다시 해줘야할지 적어줄 수 있는 역할을 함.
반응형
'패스트캠퍼스 > 자습' 카테고리의 다른 글
poiemaweb 14~15강 복습 (0) | 2019.09.20 |
---|---|
리액트 31~35강 정리 (0) | 2019.09.19 |
리액트 21~25강 정리 (0) | 2019.09.15 |
poiemaweb 8~9강 복습 (0) | 2019.09.10 |
리액트 16~20강 정리 (0) | 2019.09.09 |