보통 정보를 가져올 때 API로 가져오거나 한다
영상에서는 큰 프로젝트가 아니므로 사진을 저장하고 이를 전역 변수로 저장하는 형태로 구현한 것 같다
사진은 src/img 에 저장해서 구현했다
const items = [
{
name: "국밥",
src: require('../../img/GukBob.jpg').default
},
{
name: "햄버거",
src: require('../../img/Hamburger.jpg').default
},
{
name: "피자",
src: require('../../img/Pizza.jpg').default
},
{
name: "초밥",
src: require('../../img/Sushi.jpg').default
},
];
React 에서 Image를 불러오는 방법
Math.random() 함수는 0 ~ 1 사이의 랜덤한 값을 가진다
Javascript 배열에서 sort 함수를 이용해 배열을 정렬할 때, Math.random() - 0.5 값을 통해 임의의 -, + 값이 오게 만들어 무작위로 정렬 되도록 한다
전역변수 items로 부터 받은 값을 컴포넌트의 첫 랜더링에만 저장하도록 하기 위해 useEffect(~~, []) 를 사용하였다
const [foods, setFoods] = useState([]);
useEffect(() => {
items.sort(() => Math.random() - 0.5);
setFoods(items);
// ~~~
}, []);
해당 코드에서는 Display 하는 item을 따로 State에 크기가 2인 배열로 저장한다
const [displays, setDisplays] = useState([]);
useEffect(() => {
// ~~~
setDisplays([items[0], items[1]]);
}, []);
이 State만을 Rendering 해서 사용자에게 보여준다
return // ~~
{displays.map(item => {
return <div
className="flex-1"
key={item.name}
onClick={clickHandler(item)}
>
<img className="food-img" src={item.src} alt="food"/>
<div className="name">{item.name}</div>
</div>
})}
// ~~
이미지에 마우스를 올려놨을 때 아래의 효과들로 사용자가 이를 클릭할 수 있다는 암시를 준다
이를 styled-component인 FlexBox 안에 하위 클래스로 아래처럼 css로 적용하였다
const FlexBox = styled.div`
// ~~~
.flex-1 {
flex: 1;
min-width: 500px;
overflow: hidden;
background-color: gray;
position: relative;
}
.food-img {
width: 100%;
height: 100%;
transition: 0.5s;
cursor: pointer;
}
.food-img:hover{
transform: scale(1.1);
opacity: 0.8;
}
.name{
position: absolute;
z-index: 3;
color: #ffffff;
bottom: 10%;
font-size: 90px;
left: 50%;
transform: translateX(-50%);
}
`
사진을 클릭했을 때 사용자의 선택받은 아이템은 따로 저장되고 다음 아이템들이 Display 되어야 한다
이때 승리한 아이템을 넣는 변수를 따로 두어 저장하도록 한다
const [winners, setWinners] = useState([]);
배열에서 아이템들을 빼내어 Display 하다보면 length가 2 이하일 때까지 반복하게 된다
const clickHandler = food => (event) => {
// ~~
else if(foods.length > 2){
setWinners([...winners, food]);
setDisplays([foods[2], foods[3]]);
setFoods(foods.slice(2));
}
}
length가 2 이하일 때는 사용자가 전체 아이템을 살펴보았다는 말이 된다
그 이후에는 사용자가 선택한 아이템 중에서 월드컵을 진행하고 선택된 아이템이 하나만 남을 때 까지 아이템을 선정한다
const clickHandler = food => (event) => {
if(foods.length <= 2){
if(winners.length === 0){
setDisplays([food]);
} else{
let updatedFood = [...winners, food];
setFoods(updatedFood);
setDisplays([updatedFood[0], updatedFood[1]]);
setWinners([]);
}
//~~
}
클릭 이벤트의 전체 코드는 위 두개의 코드를 합친 것과 같다
App.js 에 다음과 같은 styled-component를 사용하여 전체 css를 적용하였다
import React from "react";
import { createGlobalStyle } from 'styled-components';
import Game from './components/Game/Game';
const GlobalStyle = createGlobalStyle`
* {
margin: 0,
padding: 0;
box-sizing: border-box;
}
`;
function App() {
return (<>
<GlobalStyle></GlobalStyle>
<Game/>
</>);
}
export default App;
게임을 실행하는 div 태그를 하나의 styled-component로 두어 style.js 에 따로 저장한다
import styled from 'styled-components';
export const FlexBox = styled.div`
// ...
`;
이를 div 태그에서 사용하여 가독성을 높인 것(?) 같다
import React, { useState, useEffect } from 'react';
import { FlexBox } from './style';
// ~~
const Game = () => {
// ~~
return <FlexBox>
// ~~
</FlexBox>;
}
Favorite WorldCup 임을 알리는 타이틀은 아래와 같은 태그를 가진다
<h1 className="title">Favorite WorldCup</h1>
이는 styled-component 안에 다음과 같이 css로 지정되어 상단 중앙에 위치하게 된다
.title {
position: absolute;
z-index: 2;
top: 0;
left: 50%;
transform: translateX(-50%);
background-color: #ffffff;
padding: 0px 30px;
padding-bottom: 10px;
text-transform: uppercase;
}
React에 대해 심화적으로 했다기 보다 styled-component 사용에 중점에 둔 프로젝트였던 것 같다