๋ณต์กํ ์ํ๊ด๋ฆฌ๋ฅผ ํตํด ๊ฐ๋จํ ์ผ๊ตฌ๊ฒ์์ ๋ง๋ค์ด ๋ณด๋ ๋ฏธ๋ ํ๋ก์ ํธ๋ฅผ ์งํํ๋ค.
๋ฐฑ์๋์์ API๋ฅผ ์ ๊ณตํด ์ฃผ์๊ณ , ๊ฐ๋จํ ๋ก์ง๊ฐ์ ๊ฒฝ์ฐ๋ FE๋จ์์ ๊ด๋ฆฌํ๊ธฐ๋ก ๊ฒฐ์ ํ๋ค.
ํ๋ก์ ํธ๋ฅผ ์งํํ๋ฉฐ ๊ฒช์๋ ํฌ๊ณ ์์ error๋ค๊ณผ ๋ฐฐ์ ๋ ์ ์ ์ ๋ฆฌํด๋ณด๊ฒ ์ต๋๋ค-!
VS Code ์ฌ์ํ ๋ฌธ๋ฒ ๋ง์ถ๊ธฐ
[ Setting -> quote ๊ฒ์ -> ์์ ]
์คํฐ๊ณผ ํจ๊ป ํ๋ก๊ทธ๋๋ฐ ํ๋ฉด์ ๋ฐ๊ฒฌํ ์ฌ์ํ ๋ฒ๊ฑฐ๋ก์์
๋ฐ๋ก VS Code ์ ์ฅ ์ ์๋ ์ ์ฉ๋๋ ๋ฌธ๋ฒ ์ค์ ์ด ๋ค๋ฅด๋ค๋ ๊ฒ
JS์์ ๋ฌธ์์ด์ด auto๋ก ๋์ด์๊ณ
Prettier ์ JSX ๋ ์ฒดํฌ๊ฐ ์๋์์์ง๋ง
single, check ๋ก ๋ง์ถ์๋ค.
mergeํ ๋ ์ด๋ฐ ์ฌ์ํ ๋ถ๋ถ์ด ๋ณ๊ฒฝ์ฌํญ์ผ๋ก ๊ธฐ๋ก๋์๊ธฐ ๋๋ฌธ์ ๊ณ ์ณ์ฃผ์๋๋ฐ ํ์ ํ ๋ ์ด๋ฐ ์ฌ์ํ ๋ฌธ์ ๋ ๋ฐ์ํ๋๊ตฌ๋ ํ๋ ํคํ๋~
+ Router ์ค์
์ค๋์ ์ฝ์ง: module์ ์ค์นํ๋ฉด ( styled-components ๋ฅผ ์ค์นํ๋ค) ์๋ฒ๋ฅผ ํ๋ฒ ๊ป๋ค ์ผ์ผํ๋๋ฐ
๋ง์์ด ๊ธํ๋ค๋ณด๋ ์๊ฐ์ ๋ชปํ๋ค.
๐ ThemeProvider ๋ก ๊ณตํต Theme ๋ง๋ค์ด ๊ด๋ฆฌํ๊ธฐ
<ThemeProvider>
: Context API๋ฅผ ํตํด ์์ฒด ์๋์ ๋ชจ๋ React ๊ตฌ์ฑ์์์ ๊ณตํต ํ ๋ง๋ฅผ ์ ๊ณตํ๋ styled-components ๋ํผ๊ตฌ์ฑ ์์
App์์ <ThemeProvider>๋ก ๊ฐ์ผ ์์ Component๋ค์ props๋ก theme์ ์ ๋ฌ๋ฐ์
๊ฐ๊ฐ์ Component์์ ๋ฐ๋ก ์ ์ธ ์์ด ์ฌ์ฉ ๊ฐ๋ฅ
์ฌ์ฉ๋ฒ
1) sytled-components ์์ ThemeProvider import
2) ๊ณตํต์ผ๋ก ์ฌ์ฉํ Component์์๋ฅผ ๊ฐ์ผ๋ค
App.jsx
import { BrowserRouter, Route, Switch } from "react-router-dom";
import { createGlobalStyle, ThemeProvider } from "styled-components";
import "./App.css";
import PlayScreen from "./routes/PlayScreen";
import StartScreen from "./routes/StartScreen";
import theme from "./theme";
function App() {
const GlobalStyle = createGlobalStyle`
* {
padding:0;
margin:0;
}
body{
box-sizing:border-box;
}
ol,ul {
list-style: none;
}
`;
return (
<ThemeProvider theme={theme}>
<GlobalStyle />
<BrowserRouter>
<Switch>
<Route path="/" exact>
<StartScreen />
</Route>
<Route path="/play-screen">
<PlayScreen />
</Route>
</Switch>
</BrowserRouter>
</ThemeProvider>
);
}
export default App;
theme.js
const theme = {
fontSizes: {
XS: "14px",
S: "16px",
M: "18px",
L: "20px",
XL: "24px",
XXL: "40px",
},
screenType: {
START: "start",
PLAY: "play",
},
};
export default theme;
์ด๋ ๊ฒ styled-components์์ ์ ๊ณตํ๋ ThemeProvider๋ฅผ ์๋จ ๋ถ๋ถ์ ๊ฐ์ธ์ฃผ๋ฉด
theme์ ์๋ ์์ฑ๋ค์ ๋ฐ๋ก import ํ ํ์ ์์ด globalํ๊ฒ ์ฌ์ฉ ๊ฐ๋ฅํ๋ค.
Component์์์ ์ฌ์ฉ
const TeamCurrent = styled.div`
font-size: ${({ theme }) => theme.fontSizes.XS};
color: ${({ theme }) => theme.colors.orange};
`;
โ ๏ธ ๋จ ์์ฑ์ผ๋ก ๋๊ฒจ์ฃผ๋ ๊ฒฝ์ฐ๋ก๋ ์ฌ์ฉ์ด ์๋๋ค ใ ใ
import Title from "../components/Title";
const PlayScreen = (props) => (
<>
<h1>playํ๋ฉด</h1>
<Title type={theme.screenType.PLAY} />
</>
);
export default PlayScreen;
์ด๋ ๊ฒ ํ๋ฉด ์๋จน์
๋๋์
์ฅ์ | ๋จ์ |
- ํ๋ก์ ํธ ์ ๋ฐ ์คํ์ผ์ ์ผ๊ด์ฑ ์๊น - ํ ๋๋ฆ์ StyleConvention์ด ์๊น |
- ์ด๊ฒ ๋ํ ํ์ convention์ด๊ธฐ ๋๋ฌธ์ ์ด๋ฐ์ ๊ท์น ์ค์ ์ ์๊ฐ์ด ์์๋จ |
๐ CRA์ public path๋ public
์ฒ์ ์ด๋ฏธ์ง๊ฒฝ๋ก๋ฅด ์ค์ ํ ๋ src ํด๋์ ๋ฃ์ด๋๊ณ ์๋๊ฒฝ๋ก๋ก ์ฐ๊ฒฐํ๋๋ img๊ฐ ๋ถ๋ฌ์์ง์ง ์์๋ค.
๊ฒ์์ ํด๋ณด๋ CRA ์์ image๋ฅผ ๋ถ๋ฌ์ฌ ๊ฒฝ์ฐ
1) ์ ๋ ๊ฒฝ๋ก ์ฌ์ฉ
2) public / images ํด๋๋ฅผ ์์ฑํด ์ฌ์ฉ
์์ ๊ฐ์ ๋ฐฉ๋ฒ์ ๊ถ์ฅํ๊ณ ์๋ค.
https://stackoverflow.com/questions/37644265/correct-path-for-img-on-react-js
image ์ฌ์ฉ component
import styled from 'styled-components';
const Stadium = () => {
return (
<StadiumDiv></StadiumDiv>
);
};
const StadiumDiv = styled.div`
box-sizing: border-box;
opacity: 90%;
background-image: url('./baseballRound.jpg');
background-position: center;
`;
export default Stadium;
public/baseballRound.jpg๋ฅผ ๋ถ๋ฌ์ ์ฌ์ฉํ๋ค.
๐ ContextAPI ์ ์ฉํ๊ธฐ
ConstextAPI๋ฅผ ์ ์ฉํ๊ธฐ ์ํด ์ ์ผ๋ค.
์ผ๋จ ๋๋ ์ฌํ๊ป ์ํ๊ด๋ฆฌ๋ฅผ ์ํด props drilling or useState ๋ง ์ฌ์ฉํด์์๋๋ฐ
์ข๋ ์์์์ props drilling์ ์ ๊ฒฝ์ฐ์ง ์๊ณ ์ํ๊ด๋ฆฌ๋ฅผ ํด์ฃผ๋ ๋ฐฉ๋ฒ์ธ ContdxtAPI์๋ํด ๊ณต๋ถํ๊ณ ์ฌ์ฉํ๊ธฐ๋ก ๊ฒฐ์ฌ!
์ฌ์ฉ๋ฒ
1) provider ์์ฑ : ์ ์ญ์ฌ์ฉํ data ์์ฑ Context.js
2) reducer ์์ฑ : useReducer ์ด์ฉํ state, dispatch ์์ฑ ( Provider์๋๊ณณ ํน์ ๋ถ๋ฆฌํด๋ ๋จ)
3) App ์์ (ํน์ ์์์์ ) Provider ๋ก ๋ฌถ์ด์ฃผ๊ธฐ - ์ด๋ reducer ํจ์ ์ ๋ฌ
4) ์ฌ์ฉํ ๊ณณ์์ importํ ์ฌ์ฉ ({state, dispatch} = useContext(newContext) )
provider/Context.jsx
import { createContext } from 'react';
const boardHistory = {
S: 0,
B: 0,
O: 0,
H: 0,
HitInfo: ' ',
};
const BoardHistoryContext = createContext();
export { boardHistory, BoardHistoryContext };
์ ์ญ์ฌ์ฉํ state ์์ฑ ( boardHistory, BoardHistoryContext)
reducer/ ballReducer.js
const ballReducer = (ballCnt, action) => {
switch (action.type) {
case 'hitS':
return { ...ballCnt, S: ballCnt.S + 1 };
case 'hitB':
return { ...ballCnt, B: ballCnt.B + 1 };
default:
return null;
}
};
export default ballReducer;
ballReducer ๋ผ๋ dispatch์ ๋ฐ๋ผ state๊ด๋ฆฌํ reducer ํจ์ ์์ฑ
App.js
import { boardHistory, BoardHistoryContext } from './components/provider/Context';
import ballReducer from './components/reducer/ballReducer';
function App() {
const [ballCnt, dispatch] = useReducer(ballReducer, boardHistory);
return (
<ThemeProvider theme={theme}>
<GlobalStyle />
<BrowserRouter>
<Switch>
<AppDiv>
<Route path='/' exact>
<StartScreen />
</Route>
<BoardHistoryContext.Provider value={{ ballCnt, dispatch }}>
<Route path='/play-screen'>
<PlayScreen />
</Route>
</BoardHistoryContext.Provider>
</AppDiv>
</Switch>
</BrowserRouter>
</ThemeProvider>
);
}
ํด๋น ์ ์ญ state๋ฅผ ์ฌ์ฉํ Component Provider๋ก ๊ฐ์ธ๊ธฐ
Stadium.jsx( ์ฌ์ฉํ๋ ์์)
import { boardHistory, BoardHistoryContext } from '../provider/ContextB';
const Stadium = () => {
const { ballCnt, dispatch } = useContext(BoardHistoryContext);
return (
<StadiumDiv>
//...์ค๋ต
<PlayButton onClick={() => playPitch(dispatch, ballCnt)}>
PITCH
</PlayButton>
</StadiumDiv>
);
};
const playPitch = (callback, ballCnt) => {
const tempBoardLst = ['S', 'B', 'H'];
var randomBoard =
tempBoardLst[Math.floor(Math.random() * tempBoardLst.length)];
callback({ type: randomBoard });
dispatch({ type: 'hitInfo', payload: randomHit });
dispatch({ type: 'hit' + randomHit });
};
useContext ์ ์ ์ ํ
PlayBoard component , playPitch ํจ์ ์ด์ฉํ์ฌ
PlayButton์ ํด๋ฆญ ์ด๋ฒคํธ ์ ๋ฌ
<PlayButton onClick={() => playPitch(dispatch, ballCnt)}>
PlayButton์ ๋๋ฅด๋ฉด ๋๋ค๊ฐ์ ๋ฐ๋ผ ballreducer์ dispatch ๊ฐ ์ ์ฉ๋๋๋ก ํ๋ค.
๐ useEffect๋ก ์ํ ๊ด๋ฆฌํ๊ธฐ
๋ด๊ฐ ์ํ๋ ๋ฃจํด์
1) ๋ฒํผ ํด๋ฆญ
2) 3๊ฐ์ง ๊ฒฝ์ฐ ์ค ํ๋ ์ ํ -> ํด๋น ๊ฐ +1 (Context ๋ก ๊ด๋ฆฌ)
3) Component๋ ํด๋น๊ฐ์ด ๋ณ๊ฒฝ๋๋ฉด ์ฌ๋ ๋๋ง
return ๋ถ๋ถ
<PlayBoardTemp type='S' />
<PlayBoardTemp type='B' />
<PlayBoardTemp type='O' />
type์ ๋ฐ๋ผ ๋ ๋๋ง
playPitch (๋ฒํผ ํด๋ฆญ์ ์คํ๋ ํจ์)
const playPitch = (ballCnt, dispatch) => {
const tempBoardLst = ['S', 'B'];
const randomHit =
tempBoardLst[Math.floor(Math.random() * tempBoardLst.length)];
console.log('1');
dispatch({ type: 'plus' + randomHit });
if (ballCnt.S > 3) {
console.log('์์์
๋๋ค');
setTimeout(() => dispatch({ type: 'plusO' }), 1000);
}
if (ballCnt.B > 4) {
console.log('์ํ์
๋๋ค');
setTimeout(() => dispatch({ type: 'plusH' }), 1000);
}
};
๋์ ์์์ผ๋ก๋
ํด๋ฆญ -> dispatch({type: 'plus' _ randomHit}); ์คํ
-> ํด๋น์กฐ๊ฑด์ ๋ง์ผ๋ฉด if ๋ฌธ์ด ์คํ ์ด์์ง๋ง
์ค์ ๋ก๋
ํด๋ฆญ -> dispatch ์ if ๋ฌธ ์คํ
-> dispatch({type: 'plus' _ randomHit}); ์คํ
์ด ์์๋ก ์งํ๋๊ธฐ ๋๋ฌธ์ ์กฐ๊ฑด์ด ๋ค์ ํด๋ฆญ์์ ์ ์ฉ ๋๋ ๊ฒ์ด๋ค.
์์ ์ PlayPitch
const playPitch = (ballCnt, dispatch) => {
const tempBoardLst = ['S', 'B'];
const randomHit =
tempBoardLst[Math.floor(Math.random() * tempBoardLst.length)];
if (ballCnt.S < 2 && ballCnt.B < 3) {
dispatch({ type: 'plus' + randomHit });
}
if (ballCnt.S === 2) {
dispatch({ type: 'plus' + randomHit });
setTimeout(() => dispatch({ type: 'plusO' }), 1000);
}
if (ballCnt.B === 3) {
dispatch({ type: 'plus' + randomHit });
setTimeout(() => dispatch({ type: 'plusH' }), 1000);
}
};
์์ ํ PlayPitch
const playPitch = (ballCnt, dispatch) => {
const tempBoardLst = ['S', 'B', 'H'];
const randomHit =
tempBoardLst[Math.floor(Math.random() * tempBoardLst.length)];
console.log(randomHit);
dispatch({ type: 'hitInfo', payload: randomHit });
dispatch({ type: 'hit' + randomHit });
};
useEffect(() => {
if (ballCnt.S === 3) {
setTimeout(() => dispatch({ type: 'hitO', payload: 'O' }), 1000);
}
if (ballCnt.B === 4) {
setTimeout(() => dispatch({ type: 'hitH', payload: 'H' }), 1000);
}
if (ballCnt.O === 3) {
setTimeout(() => dispatch({ type: 'resetAll' }), 1000);
}
}, [ballCnt]);
์์ ์ PlayPitch๋ฅผ ๋ณด๋ฉด
ballCnt ๋ฅผ ์ต์ง๋ก ์กฐ์ ํ๊ณ ์๋๊ฑธ ๋ณผ ์ ์๋ค.
๋ด๊ฐ ์ํ๋ ์ํฉ์ ์ด๊ฑธ ์์ํ์ง๋ง
1) ๋ฒํผ ํด๋ฆญ
2) dispatch ๋์ [ ballCnt +=1 ์ฆ๊ฐ ]
3) ์กฐ๊ฑด๋ฌธ ๋์ [ ์ฆ๊ฐํ์ํ์ ๊ฐ์์ S==3์ด๋ฉด ์์ B===4์ด๋ฉด ์์์ธ๋ฐ ]
(์์ ์ ์ PlayPitch์์) ๋์
1) ๋ฒํผ ํด๋ฆญ
2) ์กฐ๊ฑด๋ฌธ ๋์ [ prev dispatch ๋ก ๋์ ]
3) dispatch ๋์ [ ballCnt ++ ]
์ค์ ๋ก๋ ์ด๋ ๊ฒ ๋์ํ๋ค.
์๋๋ฉด ๋๋ ์์ ํ ์๋ชป ์๊ฐํ๋ ๊ฒ์ด ,
๋ฒํผ์ดํด๋ฆญ๋๊ณ PlayPitch๊ฐ ์คํ๋๋ฉด dispatch๊ฐ ๋์๋๋ฉด์ ์ ์ฒด Component ์ฌ ๋ ๋๋ง์ด ๋๋ค
๋ ํด๋ฆญ๋ ๋น์์ ballCnt์ ์ํ๋ ๋ด๊ฐ ์ํ ๋์์ ์ํํ๊ธฐ ์ ์ด๊ธฐ ๋๋ฌธ์
๋ค์ ํด๋ฆญ์ ๋๋ฅด๋ฉด์ ๋ณํํ ballCnt ์ํ๋ก ์กฐ๊ฑด๋ฌธ์ด ๋์ํ ์ ์๋ ๊ฒ์ด๋ค.
๊ทธ๋์ ์ฒ์์๋ ๊ตฌ์ฑ์ด ์๋ชป๋ ๊ฑธ ํ์ ํ์ง ๋ชปํ ์ฑ
์ต์ง๋ก ์ํ๋ฅผ ์ฐ๊ฒจ๋ฃ์๋ค.
useEffect๋ฅผ ์์ฑํ๊ณ ballCnt๊ฐ ๋ณ๊ฒฝ์ด ๋๋ฉด ๋ฐ๋ก ๋์ํ๋๋ก ์์ฑํ๋ค.
1) PlayPictch onClick ์คํ
2) random ํ๊ฒ dispatch ์คํ
3) ballCnt๋ณ๊ฒฝ
4) ๋ณ๊ฒฝ ์ดํ์ ์ํ๋ก if ์กฐ๊ฑด ์ ์ฉ
์ด 4๋จ๊ณ๋ฅผ ํตํด ํฌ์๊ฐ ๊ณต์ ๋์ก์ ๋ ์ผ์ด๋๋ ์ผ์ ๊ด๋ฆฌํ๋ค.
๋๋์
react์์ ์ํ๊ด๋ฆฌ์ ์ค์์ฑ์ ๋ค์๊ธ ๊นจ๋ฌ์๋ค.
ํนํ ์ํ์ ๋ฐ๋ฅธ ์กฐ๊ฑด๋ฌธ๊ณผ ๊ทธ ๊ณผ์ ์ ์ฒ๋ฆฌํ ๋
์ฝ๋๊ฐ ๋ด ์๊ฐ๋๋ก ๋์ํ ๊ฑฐ๋ผ ์๊ฐํ์ง๋ง
๋ฆฌ์กํธ๋ ์ํ๊ฐ ๊ฐ์งํจ๊ณผ ๋์์ ์ฌ ๋ ๋๋ง ๋๊ธฐ ๋๋ฌธ์
๋ฐ์ ์กฐ๊ฑด๋ค์ ๊ทธ ๋ค์์ํ๊ฐ ๋์ด์์ผ ์ ์ฉ์ด ๋๋ค๋ ์ฌ์ค์ ๊นจ๋ฌ์๋ค.
์ํ๊ด๋ฆฌ์ ๋ช์ ๋น ์ ธ์์ ๋ DD์ ๋์์ ๋ง์ด ๋ฐ์๊ณ .
DD๊ฐ ์จ์ฃผ์ ๋ธ๋ก๊ทธ์ ์ํ๊ด๋ฆฌ์ ๊ธฐ๋ณธ์ ์ธ ์๋ฆฌ๊ฐ ์ ์ค๋ช ๋์ด ์๊ธฐ ๋๋ฌธ์ ํด๋น ๐๋งํฌ๋ฅผ ๋จ๊น๋๋ค.
'๐ฟ Project' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
React๋ก Slider ๊ตฌํ & React์์ Canvas๋ก ๊ณก์ ๊ทธ๋ํ ๊ทธ๋ฆฌ๊ธฐ (+globalCompositeOperation ) (0) | 2021.06.02 |
---|---|
[SidePJ] airdnd 1๋ถ - ํ๋ก์ ํธ ์์ ! (0) | 2021.05.28 |
[side PJ ] โพ๏ธ์ผ๊ตฌ๊ฒ์ - ๋ฌธ์ ์ํฉ๊ณผ ํด๊ฒฐ๊ณผ์ (0) | 2021.05.20 |
todo List ํ๋ก์ ํธ (0) | 2021.04.10 |
์ฝ๋์ค์ฟผ๋ ๋ง์คํฐ์ฆ ํ๋ก ํธ ์๋ 1๋ฌ์ฐจ ํ๊ณ (0) | 2021.02.18 |
๋๊ธ