Container / Presentation 방식
container : 데이터 조작을 다루는 컴포넌트
presentation : 화면을 다루는 컴포넌트
CRA는 NPX로
NPX는 그 순간 최신의 소스를 받아와서 설치 후 삭제함
NPM 전역으로 CRA를 설치후 CRA를 하면, 설치 당시의 버전으로 사용해야하고,
나중에 패키지가 업데이트 되면 새로 전역에 설치해야함
또, CRA의 의존성 패키지들을 로컬에 남겨두지 않음
React + type script
npx create-react-app my-app --template typescript
React에 typescript , scss 추가
yarn add -D typescript @types/node @types/react @types/react-dom @types/jest
yarn add sass
{
"compilerOptions": {
"target": "es5",
"lib": [
"dom",
"dom.iterable",
"esnext"
],
"allowJs": true,
"skipLibCheck": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"strict": true,
"forceConsistentCasingInFileNames": false,
"noFallthroughCasesInSwitch": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "react-jsx",
},
"include": [
"src"
]
}
React + eslint + prettier + redux tool-kit
yarn add -D prettier eslint-config-prettier eslint-plugin-prettier eslint @typescript-eslint/parser @typescript-eslint/eslint-plugin
yarn add @reduxjs/toolkit react-redux react-router-dom
// .eslintrc.js
module.exports = {
env: {
browser: true,
node: true,
},
extends: [
'prettier',
'eslint:recommended',
'plugin:react/recommended',
'plugin:@typescript-eslint/recommended',
'plugin:prettier/recommended',
],
parser: '@typescript-eslint/parser',
parserOptions: {
ecmaFeatures: {
jsx: true,
},
ecmaVersion: 12,
sourceType: 'module',
},
plugins: ['react', '@typescript-eslint'],
rules: {
'prettier/prettier': ['error', { endOfLine: 'auto' }],
},
};
// .prettierrc.js
module.exports = {
// String is in single quotes (')
// 문자열은 홀따옴표(')로
singleQuote: true,
// With a semicolon at the end of the code.
// 코드 마지막에 세미콜른이 있게
semi: true,
// Do not use tabs and replace them with space bars.
// 탭의 사용을 금하고 스페이스바 사용으로 대체하게
useTabs: false,
// Indentation width of 2 spaces
// 들여쓰기 너비는 2칸
tabWidth: 2,
// When you create an object or array, you also put a comma on the element or on the back of the key-value.
// 객체나 배열을 작성 할 때, 원소 혹은 key-valueㅇ의 맨 뒤에 있는 것에도 쉼표를 붙임
trailingComma: 'all',
//One line of code is maximum 80 spaces
// 코드 한줄이 maximum 80칸
printWidth: 80,
};
filter vs find
const item = productList.find((list: productListProps) => {
return list.id === Number(id);
});
const item2 = productList.filter((list: productListProps) => {
return list.id === Number(id);
});
React Query
yarn add react-query
import { QueryClient, QueryClientProvider } from 'react-query';
const queryClient = new QueryClient();
const root = ReactDOM.createRoot(
document.getElementById('root') as HTMLElement,
);
root.render(
<React.StrictMode>
<QueryClientProvider client={queryClient}>
<Provider store={store}>
<BrowserRouter>
<App />
</BrowserRouter>
</Provider>
</QueryClientProvider>
</React.StrictMode>,
);
import axios from 'axios';
import { useQuery } from 'react-query';
import * as React from 'react';
const DashBoard = () => {
const result = useQuery(
'작명',
() =>
axios.get('https://codingapple1.github.io/userdata.json').then((a) => {
return a.data;
}),
{
refetchOnWindowFocus: false,
retry: 0,
onSuccess: (data) => {
console.log(data);
},
onError: (e) => {
console.log(e.message);
},
},
);
return (
<div>
{result.isLoading && '로딩중'}
{result.error && '에러남'}
{result.data && result.data.name}
</div>
);
};
export default DashBoard;
불변성 지키면서 배열 업데이트
let [users, setUsers] = useState([]);
# 배열에 추가
setUsers(users.concat(user));
# 배열에 추가 (함수형)
setUsers((prev) => prev.concat(user));
# 배열에서 삭제
const onRemove = id => {
setUsers(users.filter(user => user.id !== id));
};
#배열 수정
const onToggle = id => {
setUsers(
users.map(user =>
user.id === id ? { ...user, active: !user.active } : user
)
);
};
불변성 지키면서 객체(object) 업데이트
#객체에 추가 #객체 업데이트
setUsers(state => {...state, key: value})
#객체에서 제거 #loadash
setUsers(state => {..._.omit(state, 'deleteKey')})
맨 아래로 Scroll 하기
messageListRef.current?.scrollTo(0, messageListRef.current.scrollHeight);