[team-project_종합 게임 사이트 만들기] 게임 별 탭 기능 구현
팀 프로젝트 회의 결과 4가지 간단한 게임을 할 수 있는 종합 게임 사이트를 만들기로 하였다.
[ 오늘의 작업 과정 ]
1. 전체적인 UI 디자인
2. 상단의 탭을 눌렀을 때 게임별로 보여지는 기능 구현하기
리액트를 사용하였고 탭, 버튼 부분 등은 리액트 부트스트랩을 활용하였다.
1. 게임 시작 화면 구현 (App.js)
- useNavigate()를 사용해 버튼 클릭시 게임 화면(/game)으로 넘어가도록 구현했다. 첫 시작 화면은 시작할 때 한번 빼고는 공통으로 자주 쓰일 일이 없다고 판단해 따로 Content() 컴포넌트로 사용하기로 하였다.
function Content() {
let navigate = useNavigate();
return (
<div className="start">
<h2>종합 게임 즐기기</h2>
<Button
variant="primary"
className="start"
onClick={() => {
navigate("/game");
}}
>
시작하기
</Button>
</div>
);
}
2. Route 컴포넌트 사용해 경로별로 페이지 보여지도록 구현 (App.js)
- 따로 routes 폴더를 만들어 게임별로 4개의 js 파일을 만들었고 이 역시 컴포넌트화해서 App.js에서 사용하기로 하였다.
- 첫 홈페이지 부분, 각각의 4가지 게임이 보여지는 페이지 부분은 Routes, Route 컴포넌트를 사용해 경로별로 화면이 보여지도록 구현했다.
import { Route, Routes, useNavigate } from "react-router-dom";
function App() {
return (
<div className="App">
<Routes>
<Route path="/" element={<Content />} /> // 첫 게임 시작 화면
<Route
path="/game"
element={
<div className="webView">
<header>
<h2>종합 게임</h2>
// 종합 게임 화면 페이지 부분
3. 탭 기능 구현하기
- useState() 함수를 사용해 각 게임별로 탭을 눌렀을 때의 상태를 넣기로 하였다. 초깃값은 0으로 게임별로 클릭시 각각의 상태를 숫자형태(1,2,3,4)로 setTab()에 넣었다.
function App() {
let [tab, setTab] = useState(0);
return (
<div className="App">
<Routes>
<Route path="/" element={<Content />} />
<Route
path="/game"
element={
<div className="webView">
<header>
<h2>종합 게임</h2>
</header>
<div className="main">
<div className="main_content">
<Nav variant="tabs" className="nav-justified">
<Nav.Item>
<Nav.Link onClick={() => setTab(0)} eventKey="link0">
지뢰찾기
</Nav.Link>
</Nav.Item>
<Nav.Item>
<Nav.Link onClick={() => setTab(1)} eventKey="link1">
오목(2인용)
</Nav.Link>
</Nav.Item>
<Nav.Item>
<Nav.Link onClick={() => setTab(2)} eventKey="link2">
스네이크
</Nav.Link>
</Nav.Item>
<Nav.Item>
<Nav.Link onClick={() => setTab(3)} eventKey="link3">
오셀로(2인용)
</Nav.Link>
</Nav.Item>
</Nav>
<div className="tab_content">
<TabContent tab={tab} />
</div>
</div>
...
- 위에서 만들었던 게임별 컴포넌트를 탭을 누를 때마다 보여지도록 구현해야 한다. 이를 위해 따로 App.js에 TabContent() 함수를 만들어 탭 상태가 바뀔때마다 각각의 게임별 컴포넌트가 보여지도록 하였다.
- 부모 컴포넌트 App에 있던 state인 tab을 사용해야하므로 자식 컴포넌트인 TabContent()에서 props로 전송해서 사용해야 한다.
function App() {
let [tab, setTab] = useState(0);
return (
....
<div className="tab_content">
<TabContent tab={tab} />
</div>
....
}
function TabContent(props) {
return <>{[<Game1 />, <Game2 />, <Game3 />, <Game4 />][props.tab]}</>;
}
[ Trouble-shooting ]
- 사실 문제라기보다는 코드를 좀 간단하게 구현하고 싶어서ㅎㅎ. TabContent() 함수 부분에서 말이다. 위의 코드처럼 간단하게 구현하기 이전의 코드이다.
function TabContent(props){
if (props.tab == 0){
return <Game1/>
}
if (props.tab == 1){
return <Game2/>
}
if (props.tab == 2){
return <Game3/>
}
if (props.tab == 3){
return <Game4/>
}
}
- 물론 정상적으로 잘 구현되지만 코드를 줄여보고 싶었다..!
if문 대신 array 자료형을 사용해 탭 클릭에 따라 화면이 보여지도록 구현해 상단의 코드를 한줄로 깔끔하게 줄였다. props.tab이 0이면 array 자료에서 0번째 게임을 꺼내 보여준다.
function TabContent(props) {
return <>{[<Game1 />, <Game2 />, <Game3 />, <Game4 />][props.tab]}</>;
}
- 아래처럼 props를 쉽게 쓰는 방법도 있다. props라고 파라미터를 하나만 작명하는게 아니라 {state이름} 이렇게 써도 정상적으로 작동한다.
function TabContent({tab}) {
return <>{[<Game1 />, <Game2 />, <Game3 />, <Game4 />][tab]}</>;
}