-
Notifications
You must be signed in to change notification settings - Fork 35
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[최영선] sprint9 #273
The head ref may contain hidden characters: "React-\uCD5C\uC601\uC120-sprint8"
[최영선] sprint9 #273
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
이번주도 과제 제출하시느라 고생 많으셨습니다! 👍
"use strict"; | ||
/* | ||
* ATTENTION: An "eval-source-map" devtool has been used. | ||
* This devtool is neither made for production nor for readable output files. | ||
* It uses "eval()" calls to create a separate source file with attached SourceMaps in the browser devtools. | ||
* If you are trying to read the output file, select a different devtool (https://webpack.js.org/configuration/devtool/) | ||
* or disable the default devtool with "devtool: false". | ||
* If you are looking for production-ready output files, see mode: "production" (https://webpack.js.org/configuration/mode/). | ||
*/ | ||
(() => { | ||
var exports = {}; | ||
exports.id = "pages/_document"; | ||
exports.ids = ["pages/_document"]; | ||
exports.modules = { | ||
|
||
/***/ "./pages/_document.tsx": | ||
/*!*****************************!*\ | ||
!*** ./pages/_document.tsx ***! | ||
\*****************************/ | ||
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { | ||
|
||
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ Document)\n/* harmony export */ });\n/* harmony import */ var react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react/jsx-dev-runtime */ \"react/jsx-dev-runtime\");\n/* harmony import */ var react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var next_document__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! next/document */ \"./node_modules/next/document.js\");\n/* harmony import */ var next_document__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(next_document__WEBPACK_IMPORTED_MODULE_1__);\n\n\nfunction Document() {\n return /*#__PURE__*/ (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_0__.jsxDEV)(next_document__WEBPACK_IMPORTED_MODULE_1__.Html, {\n lang: \"en\",\n children: [\n /*#__PURE__*/ (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_0__.jsxDEV)(next_document__WEBPACK_IMPORTED_MODULE_1__.Head, {}, void 0, false, {\n fileName: \"C:\\\\Users\\\\최영선\\\\OneDrive\\\\문서\\\\workspace\\\\sprint_mission\\\\8-Sprint-Mission\\\\pages\\\\_document.tsx\",\n lineNumber: 6,\n columnNumber: 7\n }, this),\n /*#__PURE__*/ (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_0__.jsxDEV)(\"body\", {\n children: [\n /*#__PURE__*/ (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_0__.jsxDEV)(next_document__WEBPACK_IMPORTED_MODULE_1__.Main, {}, void 0, false, {\n fileName: \"C:\\\\Users\\\\최영선\\\\OneDrive\\\\문서\\\\workspace\\\\sprint_mission\\\\8-Sprint-Mission\\\\pages\\\\_document.tsx\",\n lineNumber: 8,\n columnNumber: 9\n }, this),\n /*#__PURE__*/ (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_0__.jsxDEV)(next_document__WEBPACK_IMPORTED_MODULE_1__.NextScript, {}, void 0, false, {\n fileName: \"C:\\\\Users\\\\최영선\\\\OneDrive\\\\문서\\\\workspace\\\\sprint_mission\\\\8-Sprint-Mission\\\\pages\\\\_document.tsx\",\n lineNumber: 9,\n columnNumber: 9\n }, this)\n ]\n }, void 0, true, {\n fileName: \"C:\\\\Users\\\\최영선\\\\OneDrive\\\\문서\\\\workspace\\\\sprint_mission\\\\8-Sprint-Mission\\\\pages\\\\_document.tsx\",\n lineNumber: 7,\n columnNumber: 7\n }, this)\n ]\n }, void 0, true, {\n fileName: \"C:\\\\Users\\\\최영선\\\\OneDrive\\\\문서\\\\workspace\\\\sprint_mission\\\\8-Sprint-Mission\\\\pages\\\\_document.tsx\",\n lineNumber: 5,\n columnNumber: 5\n }, this);\n}\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9wYWdlcy9fZG9jdW1lbnQudHN4IiwibWFwcGluZ3MiOiI7Ozs7Ozs7OztBQUE0RDtBQUU3QyxTQUFTSTtJQUN0QixxQkFDRSw4REFBQ0osK0NBQUlBO1FBQUNLLE1BQUs7OzBCQUNULDhEQUFDSiwrQ0FBSUE7Ozs7OzBCQUNMLDhEQUFDSzs7a0NBQ0MsOERBQUNKLCtDQUFJQTs7Ozs7a0NBQ0wsOERBQUNDLHFEQUFVQTs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFJbkIiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly9mZS13ZWVrbHktbWlzc2lvbi8uL3BhZ2VzL19kb2N1bWVudC50c3g/ZDM3ZCJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBIdG1sLCBIZWFkLCBNYWluLCBOZXh0U2NyaXB0IH0gZnJvbSAnbmV4dC9kb2N1bWVudCdcclxuXHJcbmV4cG9ydCBkZWZhdWx0IGZ1bmN0aW9uIERvY3VtZW50KCkge1xyXG4gIHJldHVybiAoXHJcbiAgICA8SHRtbCBsYW5nPVwiZW5cIj5cclxuICAgICAgPEhlYWQgLz5cclxuICAgICAgPGJvZHk+XHJcbiAgICAgICAgPE1haW4gLz5cclxuICAgICAgICA8TmV4dFNjcmlwdCAvPlxyXG4gICAgICA8L2JvZHk+XHJcbiAgICA8L0h0bWw+XHJcbiAgKVxyXG59XHJcbiJdLCJuYW1lcyI6WyJIdG1sIiwiSGVhZCIsIk1haW4iLCJOZXh0U2NyaXB0IiwiRG9jdW1lbnQiLCJsYW5nIiwiYm9keSJdLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///./pages/_document.tsx\n"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
영선님 이런 코드들은 Next.js에 의해 자동으로 생성된 빌드 결과물입니다. 이런 빌드 결과물은 일반적으로 Git에 포함시키지 않아요~
.gitignore
파일에 .next
을 추가해주세요.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- 지금 현재 아래처럼 되어있는 파일에 아래처럼 한줄 추가해주시고
...
/node_modules
...
.next
- 이미 .next 디렉토리가 git 커밋되어있으니, cache를 제거 후 제거된 내역을 다시 푸쉬해주시면 됩니다.
git rm -r --cached .next
git commit -m "Remove .next directory from Git"
그리고 push~
import ProductdetailPage from "./pages/ProductDetail/ProductDetailPage"; | ||
import ProductdetailPage from "./pages/ProductDetail/ProductDetailPage.tsx"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
영선님 빌드도구(webpack) 이 ProductDetailPage
파일을 찾을 때 .ts, .tsx, .js, .jsx
순서로 찾으면서 시도하니 시스템에서 자동으로 .tsx 파일을 먼저 찾아 사용할거예요~ 그래서 별도로 지금처럼 .tsx
를 작성해주지 않아도됩니다.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
위 설명드린건 모듈 해석에 메커니즘입니다!
function useFetch<T>( | ||
fetchCallback: () => Promise<T>, | ||
dependencies: any[] = [] | ||
) { | ||
const [data, setData] = useState<T | null>(null); | ||
const [error, setError] = useState<string | null>(null); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
오호 제너릭 시도 좋습니다..! 👍
@@ -11,7 +14,7 @@ const useFetch = (fetchCallback, dependencies = []) => { | |||
const result = await fetchCallback(); | |||
setData(result); | |||
setError(null); | |||
} catch (error) { | |||
} catch (error: any) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
아래와 같은 방법도 있을 것 같아요!
import { AxiosError } from 'axios';
catch (err) {
if (axios.isAxiosError(err)) {
// Axios 특정 에러 처리
const axiosError = err as AxiosError;
if (axiosError.response) {
// 서버가 2xx 범위를 벗어나는 상태 코드로 응답한 경우
setError(new Error(`Request failed with status code ${axiosError.response.status}`));
} else if (axiosError.request) {
// 요청이 이루어졌으나 응답을 받지 못한 경우
setError(new Error('No response received from the server'));
} else {
// 요청 설정 중에 문제가 발생한 경우
setError(new Error('Error setting up the request'));
}
} else {
// Axios 에러가 아닌 경우
setError(err instanceof Error ? err : new Error('An unknown error occurred'));
}
} finally {
setLoading(false);
}
{ | ||
"compilerOptions": { | ||
"target": "es5", | ||
"lib": ["dom", "dom.iterable", "esnext"], | ||
"allowJs": true, | ||
"skipLibCheck": true, | ||
"esModuleInterop": true, | ||
"strict": true, | ||
"noFallthroughCasesInSwitch": true, | ||
"module": "esnext", | ||
"moduleResolution": "node", | ||
"resolveJsonModule": true, | ||
"isolatedModules": true, | ||
"noEmit": true, | ||
"jsx": "react-jsx", | ||
"baseUrl": "./src" | ||
}, | ||
"include": ["src", "index.d.ts"] | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
tsconfig 설정 잘하셨습니다.
각각 어떤 의미가 있는지 공부해보면 좋겠어요. 🙂
컴파일 대상 파일들을 어떻게 변환할지 다양한 옵션들이 많거든요.
const handleInputChange = ( | ||
e: ChangeEvent<HTMLInputElement | HTMLTextAreaElement> | ||
) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ChangeEvent
내부는 아래처럼 생겨서 HTMLInputElement | HTMLTextAreaElement
값이 T 제너릭 위치에 들어가게 되는 원리로 동작합니다.
interface ChangeEvent<T = Element> extends SyntheticEvent<T> {
target: EventTarget & T;
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
그렇다면 아래처럼 동작이되는거겠죠!?
interface ChangeEvent< HTMLInputElement | HTMLTextAreaElement = Element> extends SyntheticEvent< HTMLInputElement | HTMLTextAreaElement > {
target: EventTarget & HTMLInputElement | HTMLTextAreaElement;
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
SyntheticEvent 내부는 또 아래처럼 생겼을거구요! 이렇게 계속해서 타입을 쫒아가다보면 왜 동작하는지 이해할 수 있습니다.
interface SyntheticEvent<T = Element, E = Event> extends BaseSyntheticEvent<E, EventTarget & T, EventTarget> {}
interface BaseSyntheticEvent<E = object, C = any, T = any> {
nativeEvent: E;
currentTarget: C;
target: T;
bubbles: boolean;
cancelable: boolean;
defaultPrevented: boolean;
eventPhase: number;
isTrusted: boolean;
preventDefault(): void;
isDefaultPrevented(): boolean;
stopPropagation(): void;
isPropagationStopped(): boolean;
persist(): void;
timeStamp: number;
type: string;
...
}
type Props = { | ||
createdAt: string; | ||
favoriteCount: number; | ||
ownerId: number; | ||
images: string[]; | ||
tags: string[]; | ||
price: number; | ||
description: string; | ||
name: string; | ||
id: number; | ||
}; | ||
|
||
function ItemList() { | ||
const [items, setItems] = useState([]); | ||
const [items, setItems] = useState<Props[]>([]); | ||
const [orderBy, setOrderBy] = useState("recent"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
여기선 네이밍이 Props
가 아니라 ItemListProps
가 되면 더 명시적이겠어요.
요구사항
기본
심화
주요 변경사항
스크린샷
멘토에게