인프런 커뮤니티 질문&답변

동우님의 프로필 이미지
동우

작성한 질문수

웹 게임을 만들며 배우는 React

숫자야구 Hooks로 전환하기(+useState lazy init)

hooks로 변환하니 다음과 같은 에러가 납니다.

작성

·

345

0

제 생각에는 초기 배열이 빈배열이어서 length를 쓸 수 없어서 나는 에러 같은데 어떻게 해결해야 할지 모르겠습니다.

답변 4

0

동우님의 프로필 이미지
동우
질문자

현영님 해결됬습니다. 너무 감사드립니당^^

0

제로초(조현영)님의 프로필 이미지
제로초(조현영)
지식공유자

setTries((prevTries) => {
          [
            ...prevTries,
            { try: value, result: `${strike}스트라이크 ${ball}볼입니다.` },
          ];
        });

여기서 return을 안 하셨습니다.

setTries((prevTries) => {
          return [
            ...prevTries,
            { try: value, result: `${strike}스트라이크 ${ball}볼입니다.` },
          ];
});

0

동우님의 프로필 이미지
동우
질문자

import React, { useState, useRef } from "react";
import Try_hooks from "./Try_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 onRefInput = useRef(null);

  const onChangeInput = (e) => {
    setValue(e.currentTarget.value);
  };

  const onSubmitForm = (e) => {
    e.preventDefault();
    if (value === answer.join("")) {
      setResult("홈런!");
      setTries((prevTries) => {
        return [...prevTries, { try: value, result: "홈런!" }];
      });
      alert(`정답입니다! 정답은 ${answer.join("")} 입니다.`);
      alert("게임을 다시 시작합니다.");
      setValue("");
      setAnswer(getNumbers());
      setTries([]);
    } else {
      console.log(answer.join(""));
      const answerArray = value.split("").map((v) => parseInt(v));
      let strike = 0;
      let ball = 0;
      if (tries.length >= 9) {
        // 10번 이상 틀렸을 때
        setResult(`10번 이상 틀려서 실패! 정답은 ${answer.join("")} 입니다.`);
        alert(`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}볼입니다.` },
          ];
        });
        setResult(`틀렸습니다. ${9-tries.length}번 남았습니다.`);
      }
    }
    onRefInput.current.focus();
  };

  return (
    <>
      <h3>{result}</h3>
      <form onSubmit={onSubmitForm}>
        <input
          type="number"
          value={value}
          onChange={onChangeInput}
          maxLength={4}
          ref={onRefInput}
        />
      </form>
      <div>시도: {tries.length}</div>
      <ul>
        {/* 반복되는 내용은 배열로 만들어서 map 함수로 반복한다. */}
        {tries.map((item, index) => {
          return (
            // key로 index를 쓰면 나중에 성능 최적화 시 문제가 되므로 쓰지 않는다.
            // 컴포넌트로 분리(큰 컴포넌트로 부터 작은 컴포넌트를 분리하는 탑다운 방식), props로 값 전달
            <Try_hooks key={item + index} value={item} index={index} />
          );
        })}
      </ul>
    </>
  );
};

export default NumberBaseball;

0

제로초(조현영)님의 프로필 이미지
제로초(조현영)
지식공유자

초기 배열이 빈 배열([])이더라도 length를 쓸 수 있습니다. 코드를 보여주세요.

동우님의 프로필 이미지
동우

작성한 질문수

질문하기