10:10 입실
리액트 노마더 강의 완강하기
서버 댓글 기능 구현하기
props는 컴포넌트에 1개의 객체로 전달됨.
props를 {}로 감싸서 넘기면 사용할 때 {props.name}이 아니라 {name}으로 쓸 수 있음. -> 구조 분해 할당
function ExampleComponent({ title, content }) {
// 여기서 title과 content는 props 객체의 속성입니다.
return <div>{title} - {content}</div>;
}
// 사용 예:
<ExampleComponent title="제목" content="내용" />
컴포넌트에 넣는 onClick은 단지 props이다.
실제 이벤트는 jsx 내에 넣어줘야 함.
import React from 'react';
function MyButton({ onClick }) {
return (
<button onClick={onClick}>
클릭하세요
</button>
);
}
function App() {
const handleClick = () => {
alert('버튼이 클릭되었습니다!');
};
return (
<div>
<MyButton onClick={handleClick} />
</div>
);
}
export default App;
의존성 배열에 지정된 값이 변경될 때 효과가 실행됨.
import React, { useState, useEffect } from 'react';
function ExampleComponent() {
const [data, setData] = useState(null);
useEffect(() => {
const fetchData = async () => {
const response = await fetch('https://api.example.com/data');
const result = await response.json();
setData(result);
};
fetchData();
}, []); // 의존성 배열이 비어 있으므로 컴포넌트가 마운트될 때만 실행됩니다.
// ...
}
seEffect Hook 내부에서 반환하는 함수는 "정리(Cleanup)" 함수라고 불리며, 이 함수는 컴포넌트가 파괴되기 전(언마운트 되기 전)에 실행
useEffect(() => {
// 부수 효과 실행
return () => {
// 컴포넌트가 언마운트되거나, 의존성이 변경되어 useEffect가 다시 실행되기 전에 호출될 정리 함수
};
}, [dependencies]); // 의존성 배열
강의보다 Next 튜토리얼이 더 깔끔하다!
리액트 기본 문법만 익히고 Next로 바로 실습해보기!
객체의 모양을 정의하고 클래스와 함께 사용하며 확장 가능성이 있는 경우 interface를 사용합니다.
유니온 타입이나 튜플, 또는 다른 복잡한 타입 조합을 정의할 때 type을 사용합니다.
JavaScript 또는 TypeScript 프로젝트에서 클래스 이름을 조건부로 결합하거나, 배열 및 객체를 이용해 클래스 이름을 동적으로 만드는 데 사용되는 작고 유용한 유틸리티 라이브러리
폴더 내 모든 페이지에 layout이 자동으로 중첩됨.
<Suspense fallback={<CardsSkeleton />}>
<CardWrapper />
</Suspense>
CardWrapper의 로딩(비동기 작업)이 완료될 때까지 fallback의 props로 지정된 컴포넌트를 표시함.
<Suspense key={query + currentPage} fallback={<InvoicesTableSkeleton />}>
<Table query={query} currentPage={currentPage} />
</Suspense>
Suspense 컴포넌트의 key prop은 상태가 변경되었는지 감지하고, 필요한 경우 해당 컴포넌트와 그 자식 컴포넌트들을 재렌더링하기 위한 목적으로 사용
검색 쿼리를 타자 입력 시 마다 보내는 건 비효율적.
사용자가 입력을 중단한 경우에만 쿼리 보내기
npm i use-debounce
import { useDebouncedCallback } from 'use-debounce';
// Inside the Search Component...
const handleSearch = useDebouncedCallback((term) => {
console.log(`Searching... ${term}`);
const params = new URLSearchParams(searchParams);
if (term) {
params.set('query', term);
} else {
params.delete('query');
}
replace(`${pathname}?${params.toString()}`);
}, 300);
try-catch 로 에러 처리 시 전역 파일 error.tsx 렌더링
단, notFound()가 존재하면 error.tsx보다 우선해서 not-found.tsx로 404 먼저 렌더링
openssl rand -base64 32
루트 layout.ts에 추가하기
import { Metadata } from 'next';
export const metadata: Metadata = {
title: {
template: '%s | Acme Dashboard',
default: 'Acme Dashboard',
},
description: 'The official Next.js Learn Dashboard built with App Router.',
metadataBase: new URL('https://next-learn-dashboard.vercel.sh'),
};
export default function RootLayout() {
// ...
}
단, 중첩된 페이지의 메타데이터는 상위 페이지의 메타데이터보다 우선 적용
즉 loot에 title 메타 데이터가 있더라도 하위에 중첩된 페이지나 레이아웃의 메타데이터가 우선 적용됨.
%s는 각 페이지의 메타테이터 값으로 대체됨.
스키마 관리하기 귀찮다고 맨날 MongoDB썼는데 이번에는 postgresQL도전해 봄.
기존 백엔드 DB를 PG로 변경
pg가 postgresQL 노드 드라이버
npm install --save @nestjs/typeorm typeorm pg
typeORM을 쓰면 repository를 따로 만들지 않아도 기본적으로 제공해주는 추상화된 레이어가 있었다. 그럼 mongodb보다 더 간편하잖아?😱