구구단 문제를 제시하는 게임이다. 추가적으로 input 유효성검사와 score 기능, 모달창 구현을 하였다. 목업 툴을 통해 대략적으로 구상해본 화면이다.
1️⃣ landomNumber1
, landomNumber2
: 랜덤으로 출력되는 숫자 두개 생성.
2️⃣ first
, second
: landomNumber1, landomNumber2를 상태값으로 저장.
3️⃣ setFirst
, setSecond
: input 입력후 새로운 랜덤 숫자 생성.
const landomNumber1 = Math.ceil(Math.random() * 9);
const landomNumber2 = Math.ceil(Math.random() * 9);
const [first, setFirst] = useState(landomNumber1);
const [second, setSecond] = useState(landomNumber2);
const onSubmitForm = useCallback<(e: React.FormEvent) => void>(
e => {
e.preventDefault();
...
setFirst(landomNumber1);
setSecond(landomNumber2);
...
},
[value]
);
1️⃣ onlyNumber
: 입력된 숫자가 0에서 9 사이의 숫자를 만족해야 한다는 정규식을 가진 replace된 문자열
2️⃣ setWarning
: onlyNumber의 조건을 만족 못할 경우 경고 문자 출력.
3️⃣ disabled
: 빈값 제출을 막기 위해 value값이 존재할 경우 제출되게 설정.
const onChangeValue = (e: React.ChangeEvent<HTMLInputElement>) => {
const onlyNumber = e.target.value.replace(/[^0-9]/g, '');
if (!onlyNumber) {
setWarning('숫자를 입력해주세요');
}
setValue(onlyNumber);
};
...
<form onSubmit={onSubmitForm}>
<input
ref={inputNum}
type="text"
value={value}
onChange={onChangeValue}
className=" border-4 border-[#5061b3] text-center "
/>
<button type="submit" disabled={!value}></button>
</form>
input에 입력한 값이 저장된 value
가 랜덤숫자로 설정된 first
,second
의 곱의 결과와 같은지 다른지를 판단하여 정답
, 땡
을 출력. 그리고 value
값은 빈값으로 초기화.
const onSubmitForm = useCallback<(e: React.FormEvent) => void>(
e => {
e.preventDefault();
if (parseInt(value) === first * second) {
setResult('정답 🙆♂️');
setValue('');
...
} else {
setResult('땡 🙅♂️');
setValue('');
...
}
...
},
[value]
);
1️⃣ 횟수설정
: input입력마다 chance값이 1씩 증가한다. 만약 chance가 10이 되면 게임은 끝나고 모달창이 출력된다.
2️⃣ 모달창
: 모달창에는 해당 게임의 이름과 점수를 전달한다.
💡 모달창
: 모달창 하나를 재사용하기 위하여 게임마다 보여줘야할 결과를 props로 Modal컴포넌트에 전달한다.
자세히 👉 모달창 기능 구현
const onSubmitForm = useCallback<(e: React.FormEvent) => void>(
e => {
e.preventDefault();
...
if (!(chance === 10)) {
setChance(prevChance => (prevChance += 1));
}
...
},
[value]
);
{chance === 10 && <Modal gugudanScore={score} gugudan={'구구단'} />}
1️⃣ Score
: 작성한 값이 답일 경우에는 score가 10씩 증가하도록 설정.
2️⃣ Cursor
: 마우스 커서는 페이지 렌더링시 focus되게 useEffect 사용.
(input 입력후에도 마우스커서를 focus하기 위하여 답 입력후에도 inputNum.current?.focus()
를 작성하였는데, 그러지 않아도 커서가 잘 적용된다. 아마 다른 곳으로 커서 이동을 하지 않고 계속하여 value값이 변경되어서 그런거 같다.)
const inputNum = useRef<HTMLInputElement>(null);
useEffect(() => {
inputNum.current?.focus();
});
const onSubmitForm = useCallback<(e: React.FormEvent) => void>(
e => {
e.preventDefault();
...
if (parseInt(value) === first * second) {
...
setScore(prevScore => (prevScore += 10));
}
...
},
[value]
);
...
<input ref={inputNum} .../>
<div> Score: {score} <div/>