[React] 프로젝트 기초 공사
To Do.
- 폰트 세팅
- 레이아웃 세팅
- 이미지 에셋 세팅
- 공통 컴포넌트 세팅
폰트 세팅
https://fonts.google.com/ 에서 사용
거기서 폰트트 추가해서 @import 부분에서 style 태그를 제외한 나머지를 복사해서 붙혀넣기 한다
레이아웃 세팅
@import url("https://fonts.googleapis.com/css2?family=Nanum+Pen+Script&family=Yeon+Sung&display=swap");
body {
background-color: #f6f6f6;
display: flex;
justify-content: center;
align-items: center;
font-family: "Nanum Pen Script";
min-height: 100vh;
margin: 0px;
}
@media (min-width: 650px) {
.App {
width: 640px;
}
}
@media (max-width: 650px) {
.App {
width: 90vw;
}
}
#root {
background: white;
box-shadow: rgba(100, 100, 111, 0.2) 0px 7px 20px 0px;
}
.App {
min-height: 100vh;
padding-left: 20px;
padding-right: 20px;
}
- body: 페이지 전체에 해당
- #root: root 아래에 있는 모든 컴포넌트에 해당
- .App: App 컴포에만 해당
이미지 에셋 세팅
import "./App.css";
import { BrowserRouter, Routes, Route } from "react-router-dom";
import Home from "./pages/Home";
import New from "./pages/New";
import Edit from "./pages/Edit";
import Diary from "./pages/Diary";
function App() {
return (
<BrowserRouter>
<div className="App">
<h2>App.js</h2>
<img src={process.env.PUBLIC_URL + `/assets/emotion1.png`} />
<img src={process.env.PUBLIC_URL + `/assets/emotion2.png`} />
<img src={process.env.PUBLIC_URL + `/assets/emotion3.png`} />
<img src={process.env.PUBLIC_URL + `/assets/emotion4.png`} />
<img src={process.env.PUBLIC_URL + `/assets/emotion5.png`} />
<Routes>
<Route path="/" element={<Home></Home>}></Route>
<Route path="/new" element={<New></New>}></Route>
<Route path="/edit" element={<Edit></Edit>}></Route>
<Route path="/diary/:id" element={<Diary></Diary>}></Route>
</Routes>
</div>
</BrowserRouter>
);
}
export default App;
이미지 불러오기
공통 컴포넌트 세팅
공통으로 사용되는 버튼이나 헤더 컴포넌트 세팅하는 작업이다. 해당 버튼은 type=positive, negative, default로 나뉘고, 버튼 위의 text와 onClick 했을 때의 이벤트를 필요로 한다.
step 1. 일단 버튼 컴포 만들고 스타일링
// src > components > MyButton.js
const MyButton = ({ text, type, onClick }) => {
return (
<button className={"MyButton"} onClick={onClick}>
{text}
</button>
);
};
export default MyButton;
App.js에 MyButton 컴포넌트 넣어주기
/* App.css */
/* MyButton */
.MyButton {
cursor: pointer;
border: none;
border-radius: 5px;
padding-top: 10px;
padding-bottom: 10px;
padding-left: 20px;
padding-right: 20px;
font-size: 18px;
white-space: nowrap;
font-family: "Nanum Pen Script";
}
type에 따라 버튼 색깔 다르게 하기
// src > components > MyButton.js
const MyButton = ({ text, type, onClick }) => {
const btnType = ["positive", "negative"].includes(type) ? type : "default";
return (
<button
className={["MyButton", `MyButton_${type}`].join(" ")}
onClick={onClick}
>
{text}
</button>
);
};
MyButton.defaultProps = {
type: "default",
};
export default MyButton;
type의 이름은 className에 같이 지정해버리는 것이다. 여기서 공통 속성인 MyButton 안에 MyButton_type 을 통해서 디자인은 비슷하지만 색깔을 다르게 지정할 수 있는 것이다.
/* MyButton */
.MyButton {
cursor: pointer;
border: none;
border-radius: 5px;
padding-top: 10px;
padding-bottom: 10px;
padding-left: 20px;
padding-right: 20px;
font-size: 18px;
white-space: nowrap;
font-family: "Nanum Pen Script";
}
.MyButton_default {
background: #ececec;
color: black;
}
.MyButton_positive {
background: #64c064;
color: white;
}
.MyButton_negative {
background: #fd565f;
color: white;
}
step 2. 헤더 만들기
헤더 컴포넌트를 만들고, 인자로 받을 값들을 지정한다.
const MyHeader = ({ headText, leftChild, rightChild }) => {
return (
<header>
<div className="head_btn_left">{leftChild}</div>
<div className="head_text">{headText}</div>
<div className="head_btn_right">{rightChild}</div>
</header>
);
};
export default MyHeader;
그런 다음 App 컴포넌트에 넣고 css 스타일링
// src > App.js
<MyHeader
headText={"App"}
leftChild={
<MyButton text={"왼쪽 버튼"} onClick={() => alert("왼쪽 클릭")}></MyButton>
}
rightChild={
<MyButton
text={"오른쪽 버튼"}
onClick={() => alert("오른쪽 클릭")}
></MyButton>
}
></MyHeader>
/* src > App.css */
/* Header */
header {
padding-top: 20px;
padding-bottom: 20px;
display: flex;
align-items: center;
border-bottom: 1px solid #e2e2e2;
}
header > div {
display: flex;
}
header .head_text {
width: 50%;
font-size: 25px;
justify-content: center;
}
header .head_btn_left {
width: 25%;
justify-content: start;
}
header .head_btn_right {
width: 25%;
justify-content: end;
}
header button {
font-family: "Nanum Pen Script";
}
상태 관리 세팅하기
리액트 기본에서 사용했던 useReducer 훅을 사용한다.
const reducer = (state, action) => {
let newState = [];
switch (action.type) {
case "INIT": {
return action.data;
}
case "CREATE": {
const newItem = {
...action.data,
};
newState = [newItem, ...state];
break;
}
case "REMOVE": {
newState = state.filter((it) => it.id !== action.targetId);
break;
}
case "EDIT": {
newState = state.map((it) =>
it.id === action.data.id ? { ...action.data } : it
);
break;
}
default:
return state;
}
return newState;
};
그리고 App 컴포넌트에 Create, Remove, Edit 에 해당하는 코드를 작성한다.
const [data, dispatch] = useReducer(reducer, []);
const dataId = useRef(0);
// CREATE
const onCreate = (date, content, emotion) => {
dispatch({
type: "CREATE",
data: {
id: dataId.current,
date: new Date(date).getTime(),
content,
emotion,
},
});
dataId.current += 1;
};
// REMOVE
const onRemove = (targetId) => {
dispatch({ type: "REMOVE", targetId });
};
// EDIT
const onEdit = (targetId, date, content, emotion) => {
dispatch({
type: "EDIT",
data: {
id: targetId,
date: new Date(date).getTime(),
content,
emotion,
},
});
};
프로젝트 State Context 세팅하기
// src > App.js
export const DiaryStateContext = React.createContext();
을 통해서 내보내줄 컴포넌트 만듬.
// src > App.js
return (
<DiaryStateContext.Provider value={data}>
<BrowserRouter>
<div className="App">
<Routes>
<Route path="/" element={<Home></Home>}></Route>
<Route path="/new" element={<New></New>}></Route>
<Route path="/edit" element={<Edit></Edit>}></Route>
<Route path="/diary/:id" element={<Diary></Diary>}></Route>
</Routes>
</div>
</BrowserRouter>
</DiaryStateContext.Provider>
);
<DiaryStateContext.Provider value={data}>
을 통해서 value 값으로 data를 전달해주어서 Props 드릴링 문제를 해결한다.
프로젝트 Dispatch Context 세팅하기
export const DiaryDispatchContext = React.createContext();
return (
<DiaryStateContext.Provider value={data}>
<DiaryDispatchContext.Provider value=>
<BrowserRouter>
<div className="App">
<Routes>
<Route path="/" element={<Home></Home>}></Route>
<Route path="/new" element={<New></New>}></Route>
<Route path="/edit" element={<Edit></Edit>}></Route>
<Route path="/diary/:id" element={<Diary></Diary>}></Route>
</Routes>
</div>
</BrowserRouter>
</DiaryDispatchContext.Provider>
</DiaryStateContext.Provider>
);
<DiaryDispatchContext.Provider value=>
을 이용해 한 번 더 감싸준다.
- DiaryStateContext: 데이터 state 관련 Context 컴포넌트
- DiaryDispatchContext: 메소드 관련 Context 컴포넌트
댓글남기기