ringle에서 새로 진행하는 프로젝트인 turnchat에서 내준 과제를 하면서 배운 것들을 정리해볼까 합니다.
과제 전형은 5시간이었는데 모든 기능을 완성하지는 못했습니다.
음... 해당 프로젝트는 아마 웹팩 실험장으로 앞으로도 쓸 것 같습니다.
(--- 최근에는 TS 기반 웹팩만 쓰고 있습니다. 이제 TS없이는 살지 못하는 몸 ---)
github.com/DarrenKwonDev/awesomeForm
1. CRA없이 React 빌드해보기! (webpack. 4.42.0 사용)
2. Redux 대신 Context API 사용해보기
Redux thunk, promises 등을 사용할 이유가 없이 전역적으로 state를 관리만 하면 된다고 계산이 섰고, 굳이 다른 의존성을 설치하여 무겁게 만들고 싶지 않았기 때문에 context api를 사용해보았습니다.
그리고 당연하지만 useContext 훅을 사용했습니다. 요새 누가 Consumer HOC으로 감싸나요 ㅎ..
./ContextApi.js
import React, { createContext, useState } from "react";
// context 생성
export const AppContext = createContext();
// provider 생성
const AppContextProvider = ({ children }) => {
const [QuestionArr, setQuestionArr] = useState([
{
id: Date.now(),
type: "SingleChoice",
title: "",
detail: "",
options: [
{ optionId: Date.now() + Math.random(), text: "" },
{ optionId: Date.now() + Math.random(), text: "" },
],
},
]);
return <AppContext.Provider value={{ QuestionArr, setQuestionArr, addQuestion, formInfo }}>{children}</AppContext.Provider>;
};
export default AppContextProvider;
./src/index.js에 감싸기
ReactDOM.render(
<AppContextProvider>
<ThemeProvider theme={theme}>
<App />
</ThemeProvider>
</AppContextProvider>,
document.getElementById("root")
);
각 컴포넌트에서 useContext를 통해 사용할 수 있다.
import React, { useContext } from "react";
import { AppContext } from "../ContextApi";
function TextArea({ initialValue = "", placeholder = "", fontSize = 16, belonging, id }) {
const context = useContext(AppContext);
...
3. styled-components의 theme을 이용한 일관성 있는 디자인 + mobile-first!
Next-Cineps 만들면서 느낀 점인데 mobile-first를 안 쓰고 큰 화면에서 점차 작은 화면으로 줄여나가는 방식을 쓰니 너무 너무 x 100 불편했다. 이번에 처음으로 mobile-first를 적용해보기로 했다.
// px to rem
const calcRem = (px) => `${px / 16}rem`;
const colors = {
black: "#000000",
white: "#FFFFFF",
grayOne: "#F7F9FF",
grayTwo: "#C3C3C3",
pointColor: "#3062B9",
dangerColor: "#FF4D4F",
};
const fontSizes = {
small: calcRem(14),
base: calcRem(16),
lg: calcRem(18),
xl: calcRem(20),
xxl: calcRem(22),
xxxl: calcRem(24),
};
const paddings = {
small: calcRem(8),
base: calcRem(10),
lg: calcRem(12),
xl: calcRem(14),
xxl: calcRem(16),
xxxl: calcRem(18),
};
const margins = {
small: calcRem(8),
base: calcRem(10),
lg: calcRem(12),
xl: calcRem(14),
xxl: calcRem(16),
xxxl: calcRem(18),
header: calcRem(16 * 4),
};
const deviceSizes = {
tablet: `@media all and (min-width: 767px) and (max-width: 1023px)`,
desktop: `@media all and (min-width: 1023px)`,
};
const theme = {
colors,
fontSizes,
paddings,
margins,
deviceSizes,
};
export default theme;
사용은 다음과 같이 하면 된다! 아이구 편해라
${(props) => props.theme.deviceSizes.tablet} {
display: grid;
grid-template-columns: auto 750px auto;
}
4. atomic design (atom => molecule => components => pages)
음.. 이것도 이번 프로젝트에 처음 써 본 방법인데 장점도 있지만 솔직히 말해 조금 불편했다.
장점 : 다른 Molecule에 쓰일 Atom을 내부 폴더에 저장하지 않으므로 Atom을 자유롭게 여기저기에다 쓸 수 있다.
단점 : 어떤 Molecule에 어떤 Atom이 쓰였는 지 한 눈에 파악하기가 어렵다.
과거에는 아래와 같은 방식으로 짰는데 atomic 디자인을 활용하면 무슨 컴포넌트에 무슨 부분 컴포넌트가 들어갔는지 한 눈에 파악하기 어려운 점이 있었다. 이 파일 구조는 velopert 프로젝트에서 처음 봤는데 이 분도 다음 프로젝트에서 부터는 안 쓰시더라... React 폴더 구조는 항상 어려운 부분이다.
📁 Components
ㄴ 📁 Questions
ㄴ 📁 partials
ㄴ Radio ...
ㄴ CheckBox ...
ㄴ 📁 FAB
ㄴ 📁 partials
ㄴ ...
5. React.memo
재렌더링을 막기 위해 컴포넌트를 다 분리해놓고 React.memo를 안해서 렌더링이 다시 되는 걸 놓쳤다.
면접 보다가 뜬금없이 React.memo가 생각나서 해당 과제에 적용해봤는데 잘된다.
배열을 map, filter 등으로 뿌려줄 때 여러번 렌더링되는 컴포넌트는 React.memo로 꼭 묶어두자.
etc. 그 밖의 세세한 팁들
* text-area 글자에 따라 자동으로 늘어나게끔 설정하기
useEffect(() => {
textareaRef.current.style.height = "auto";
// 2px 안 더하면 옆에 스크롤 생김
textareaRef.current.style.height = textareaRef.current.scrollHeight + 2 + "px";
}, [text]);
* focus 잡힐 때마다 스타일링
&:focus {
transition: border-bottom 0.1s ease-in-out;
border-bottom: 4px solid ${(props) => props.theme.colors.pointColor};
}
'📑 Project > 📑 프로젝트 후기' 카테고리의 다른 글
snu-mud-webgame (0) | 2021.12.22 |
---|---|
snu-coin 거래소 (0) | 2021.06.13 |
Fuze) Next.ts + node.ts 배포 과정 (0) | 2021.02.26 |
youtube-clone (Node+Pug+freenom+Cloudflare) (0) | 2020.10.27 |
meme 공유 사이트 개발 (0) | 2020.09.05 |