오래전부터 개인적으로 만들고 싶은 게임을 만들어 봤습니다.
이번 영상은 스도쿠의 틀을 만드는 영상입니다.
버튼을 누르면 아래 숫자를 선택할 수 있는 모달이 나오고
숫자를 클릭하면 해당 칸의 숫자가 변합니다.
스도쿠의 특징인 9x9의 숫자 칸을 만들었고 이 칸을 9개로 나눠 노란색 선으로 구분지었습니다.
.container {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100vh;
}
.boxContainer {
display: grid;
grid-template-columns: repeat(9, 1fr);
}
각각의 숫자 칸들은 grid를 통해 나눠져 있으며 한 행에 9개의 열이 있도록 css했습니다.
NumberSquare.tsx
import React, { useRef, useState, useEffect } from "react";
import { NumberSquareStyle } from "./NumberSquare.styles";
import ChooseNumber from "../choosenumber/ChooseNumber";
interface Props {
number: number;
boxIndex: number;
setNumber: (index: number) => void;
}
const NumberSquare = ({ number, boxIndex, setNumber }: Props) => {
const [open, setOpen] = useState(false);
const ref = useRef<HTMLDivElement>(null);
const row = Math.floor(boxIndex / 9);
const col = boxIndex % 9;
const borderStyles = `
${row % 3 === 2 && row !== 8 ? "border-bottom: 2px solid #fff123;" : ""}
${col % 3 === 2 && col !== 8 ? "border-right: 2px solid #fff123;" : ""}
`;
const handleClick = () => {
setOpen((value) => !value);
};
const handleClickOutside = (e: MouseEvent) => {
if (ref.current && !ref.current.contains(e.target as Node)) {
setOpen(false);
}
};
useEffect(() => {
document.addEventListener("mousedown", handleClickOutside);
return () => {
document.removeEventListener("mousedown", handleClickOutside);
};
}, []);
return (
<NumberSquareStyle.Container
ref={ref}
onClick={handleClick}
borderStyles={borderStyles}
isOpen={open}
>
<NumberSquareStyle.Number>{number}</NumberSquareStyle.Number>
{open && <ChooseNumber setNumber={setNumber} setIsOpen={setOpen} />}
</NumberSquareStyle.Container>
);
};
export default NumberSquare;
위 컴포넌트에선 borderStyles가 눈에 띕니다.
borderStyles는 노란색 선을 나타내는 css입니다.
open의 값이 true가 된다면
아래 컴포넌트가 켜지게 됩니다.
ChooseNumber.tsx
import React from "react";
import { ChooseNumberStyle } from "./ChooseNumber.styles";
// any 변경 예정
interface Porps {
setNumber: any;
setIsOpen: React.Dispatch<React.SetStateAction<boolean>>;
}
const ChooseNumber = ({ setNumber, setIsOpen }: Porps) => {
const handleClick =
(index: number) => (e: React.MouseEvent<HTMLDivElement>) => {
e.stopPropagation();
setNumber(index);
setIsOpen(false);
};
return (
<ChooseNumberStyle.Container>
{Array(10)
.fill(0)
.map((_, index) => {
return (
<ChooseNumberStyle.NumberBox
key={index}
onClick={handleClick(index)}
>
<ChooseNumberStyle.Number>{index}</ChooseNumberStyle.Number>
</ChooseNumberStyle.NumberBox>
);
})}
</ChooseNumberStyle.Container>
);
};
export default ChooseNumber;
handleClick함수를 누르면 선택했던 칸의 숫자가 바뀌고 모달이 꺼집니다.
이 때 변수를 두 번 받는 함수를 만들었는데, index와 e(이벤트 객체)를 나눠 받습니다.
handleClick과 같은 함수를 커링함수라고 부릅니다.
e.stopPropagation()을 적용하기 위해서 인데, 이벤트 버블링을 막기 위해 작성했습니다.
'프로젝트' 카테고리의 다른 글
간단한 로그인 프로젝트 (redux-toolkit, sessiontStorage) (0) | 2023.06.06 |
---|---|
소셜미디어 프로젝트 도연피디아 (0) | 2023.01.10 |
운동 선수 순위권 출력 프로젝트 (0) | 2022.12.13 |
Figma -> React 프로젝트 로그인 페이지 퍼블리싱 (0) | 2022.12.12 |
Figma -> React 프로젝트 대쉬보드 퍼블리싱 (0) | 2022.12.12 |