🐈오늘 배운 것
✔️리액트 웹팩으로 빌드하기
- 필요 라이브러리
npm i react react-dom
npm i webpack webpack-cli -D
npm i style-loader -D
npm i html-webpack-plugin -D
# jsx => js 변환을 위한 babel 및 babel 구동을 위한 하위 라이브러리 추가
npm i babel-loader @babel/core @babel/preset-env @babel/preset-react -D
- webpack.config.js 설정
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'docs'),
filename: 'bundle.js',
},
module: {
rules: [
// 바벨
{test: /\.(js|jsx)$/, use: ['babel-loader'], exclude: /node_modules/},
{
test: /\.css$/,
// 오른쪽부터 왼쪽, css -> style 의 순서로 적용되므로 순서에 유의한다.
use: [MiniCssExtractPlugin.loader, 'css-loader'],
// loader가 node_modules 안의 내용도 처리하므로 예외처리
exclude: /node_modules/,
},
],
},
plugins: [
new HtmlWebpackPlugin({
template: path.resolve(__dirname, 'public', 'index.html'),
}),
new MiniCssExtractPlugin({
filename: 'common.css',
}),
],
};
- babel.config.js
module.exports = {
presets: [
['@babel/preset-env'],
['@babel/preset-react', { runtime: 'automatic' }],
],
};
리액트의 경우 JSX 문법의 변환이 필요하기 때문에 babel-loader 를 필수적으로 사용해야한다. babel 에 대한 설정은 babel.config.js 파일을 새롭게 생성하여 preset 을 추가해주면 된다. runtime : 'automatic' 옵션이 추가되어야 정상동작한다.
✔️Custom Input 컴포넌트에 react hook form 적용하기
커스텀으로 만든 Input 컴포넌트에 register 함수를 사용해 상태와 이벤트를 등록하고 싶을 때는, register 함수의 실행 결과값을 props로 보내서 적용시키는 방법이 있다.
// enter 페이지
<Input
// useForm 에서 추출한 register 함수를 호출한 결과값을 props로 전달중...
register={register('phone', {
required: true,
})}
name="phone"
label="Phone number"
type="number"
kind="phone"
required
/>
// input 컴포넌트
// 전달되는 props에 맞춰서 각 엘리먼트에 적용시켜주면 된다.
import type {UseFormRegisterReturn} from 'react-hook-form';
interface InputProps {
label: string;
name: string;
kind?: 'text' | 'phone' | 'price';
register: UseFormRegisterReturn;
type: string;
required: boolean;
}
추가적으로 현재 캐럿마켓 클론코딩에서 여러 형태의 input 컴포넌트들을 하나의 컴포넌트로 관리하면서, props로 전달되는 kind 값에 따라 조건부로 리턴하고 있다. kind 속성을 확인해서 이게 email 에 쓰일 input인지, phone 에 쓰일 input인지 확인하기 때문에 비슷한 컴포넌트를 여러개 만들지 않고도 편하게 관리할 수 있다..! 생각하지 못했던 방법이라 신기하다.
✔️API 요청을 위한 커스텀 훅 생성
자주 사용되는 기능은 함수 - 커스텀 훅으로 만들어서 사용하는 방법이 있다. enter 페이지에서는 로그인을 위해 로그인 데이터를 body에 실어 서버로 POST 요청을 보내야 하는데, 이 POST 요청을 보내는 부분을 커스텀 훅으로 만들어서 다른 페이지에서도 재사용 할 수 있다.
1. hook을 만들기 전에 먼저 어떤 기능을 hook으로 만들 것인지 정의하고,
2. 그 hook을 불러와서 어떻게 사용할 것인지 정의해본다.
3. 이렇게 두 단계를 거치면 어떤 로직을 거쳐 어떤 데이터를 리턴해야하는지 명확해진다.
클라이언트가 API 서버로 POST 요청을 보낼 때 body 에 실어서 보내는 데이터의 타입이 무엇인지 명확하게 명시해줘야한다. Content-Type 에 대한 정의가 없을 경우 서버쪽에서 데이터에 올바르게 접근할 수 없다.
+) ... 타입스크립트를 사용해보면서 타입을 지정하는 것에 조금 익숙해지고 있다. 시간을 내어 제대로 공부하는 것이 맞겠지만...
아무튼, 타입을 명시해주는 것에도 여러 방법이 있는 것 같다. 함수의 이름과 각 매개변수 이름 옆에 콜론을 붙여 각각 명시해주는 방법, 그리고 interface 와 type 이라는 키워드를 사용해 한번에 선언하는 방법
// 1
export default function useMutation(
url: string,
): [
(data: any) => void,
{loading: boolean; data: undefined | any; error: undefined | any},
] {...}
// 2
interface UseMutationState {
loading: boolean;
data?: object;
error?: object;
}
type UseMutationResult = [(data:any)=>void, UseMutationState];
export default function useMutation(url: string): UseMutationResult {...}
✔️함수형 컴포넌트에서 객체 타입의 state 업데이트
useState 로 여러개의 state를 만드는 대신, 하나의 state를 생성하고 그 안에 객체 형태로 state를 정의하는 방법이 있다. 이 때 이 상태값을 이전 상태값을 사용해 업데이트하기 위해서 prevState 값을 이용해야하는데, 아래와 같이 활용할 수 있다. 이전의 상태값을 받아서 새로운 상태로 업데이트하는 함수를 콜백 함수로 전달해준다.
setState(prev => ({...prev, loading: false}))
prevState를 사용하지 않고 그대로 state를 리턴했더니 코드가 동작하지 않았다.
🐈오늘의 느낀 점
1. 숙련자가 작성한 코드 레퍼런스를 통해 많이 배워야겠다. 이전까지는 내가 짠 코드를 누군가 잘 평가해줬으면 좋겠다고만 생각했지, 내가 다른 사람의 코드를 보고 배울 생각은 미처 하지 못했던 것 같다. 이번에 클론코딩을 하면서 니꼬의 레퍼런스 코드를 보고 많이 배우게 되었다. 코드를 보고 이런 식으로 동작하겠구나 유추하는 것도 큰 공부가 되는 것 같음.
'TIL' 카테고리의 다른 글
[TIL] 2022-1003 (0) | 2022.10.03 |
---|---|
[Day 73] 2022-0928 (1) | 2022.09.29 |
[Day 71] 2022-0926 (0) | 2022.09.27 |
[Day 66] 2022-0921: 트리/그래프 자료구조, 알고리즘, 스터디? (1) | 2022.09.22 |
[Day 65] 2022-0920: 스택/큐 자료구조 & Tailwind CSS (0) | 2022.09.21 |