리액트에서 state를 직접 바꾸는건 금지!

리랜더해주는 조건이 예전 state와 현재 state가 달라야 리랜더를 해주는데 직접 바꿔버리면 달라지지 않는다.

그래서 불변성을 잘 지켜야함. 

특히 객체나 배열! 주의

tries: [...tries, `${this.state.value}: 홈런!`],

-기존 배열을 유지시켜주고 싶다면 spred 연산자를 사용해주면 좋다.

-this.state.tries[0] = 10;, this.state.tires.push(20);      <----이런식으로 하면 안됌!!

 

직접 만든 전체코드

import React, {Component} from "react";
import Try from "./try";

//숫자 내게 랜덤으로 뽑기 함수
function getNumbers(){
    const numbers = new Array(9).fill(0).map((v,i)=>v+i+1);
    const shuffle = [];
    while(numbers.length > 0){
        const rand = Math.floor(Math.random() * numbers.length);
        const number = numbers.splice(rand,1)[0];
        shuffle.push(number);
    }
    console.log(shuffle);
    return shuffle.slice(0,4);
}


class NumberBaseball extends Component{
    state = {
        value:'',
        result:'',
        answer : getNumbers(),
        tries:[],
    }
    onChangeInput = e => {
        const value = e.target.value;
        this.setState({value});
    }

    onSubmitForm = e => {
        e.preventDefault();
        const tries = this.state.tries;
        const ans = this.state.answer.join('')
        if(this.state.value === ans){
            this.setState({
                result: '홈런!',
                value: '',
                tries: [...tries, `${this.state.value}: 홈런!`],
            });
            alert('게임을 재시작합니다.');
            this.setState({
                value:'',
                answer: getNumbers(),
                tries: [],
                result:'',
            })
        } else {
            //볼, 스트라이크 판단
            let ball = 0;
            let strike = 0;

            if(this.state.tries.length >= 9){
                this.setState({
                    result : `10번 넘게 틀려서 실패! 정답은 ${ans} 였습니다`,
                    tries,
                });
                setTimeout(()=>{
                    alert('게임을 재시작합니다.');
                    this.setState({
                        value:'',
                        answer: getNumbers(),
                        tries: [],
                        result:'',
                    })
                },10);
            }else{
                for (let i = 0; i < this.state.value.length; i++) {
                    if (this.state.value[i] === ans[i]) {
                        strike++;
                    } else if (this.state.value.indexOf(ans[i]) > -1) {
                        ball++;
                    }
                }
                if(ball === 0 && strike === 0){ //out
                    tries.push(`${this.state.value}: OUT!`);
                }else{
                    tries.push(`${this.state.value}: ${strike}S ${ball}B`);
                }

                this.setState({
                    value: '',
                    result:'땡',
                    tries,
                });
            }

        }
        this.input.focus();
    }

    input;
    onRefInput = c =>{
        this.input = c;
    }
    fruits = [
        {fruit: '사과', taste:'맛없다.'},
        {fruit: '바나나', taste:'맛없다.'},
        {fruit: '호랑이', taste:'맛없다.'},
        {fruit: '구울', taste:'맛없다.'},
        {fruit: '구렁이', taste:'맛없다.'},
        {fruit: '고우와니', taste:'맛없다.'},
    ]

    render() {
        return (
            <>
                <h1>{this.state.result}</h1>
                <form onSubmit={this.onSubmitForm}>
                    <input type="text" maxLength={4} ref={this.onRefInput} value={this.state.value} onChange={this.onChangeInput}/>
                    <button>입력</button>
                </form>
                <div>시도: {this.state.tries.length}</div>
                <ul>
                    {
                        this.state.tries.map((v,i) => {
                            return (<Try key={v+i} value={v} index={i+1} />);
                        })
                    }
                </ul>
            </>
        );
    }
}
export default NumberBaseball;

NumberBaseball.jsx

 

import React, {Component} from "react";

class Try extends Component{
    render() {
        return (
        <li>
            {this.props.index}. <b>{this.props.value}</b>
        </li>
        );
    }
}
export default Try;

 

Try.jsx

+ Recent posts