티스토리 뷰

배열에 새로운 값을 넣을때 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
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/07   »
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
글 보관함