Next.jsに改めて入門しようと思い、公式サイトの「Learn Next.js」というチュートリアル(?)をやっていきます。
かなり長いチュートリアルだったので複数回に分け紹介しており、こちらの記事はChapter1~Chapter4の内容になります。
なお記事の内容は下記に注意してご覧くださいm(_ _)m
- こちらの記事は2023年11月5日現在の情報になります。
- 公式サイトのチュートリアルを翻訳し(主にGoogle翻訳を使わせていただきました)、僕自身の解釈や理解を伝えるものになります。
- わかりやすくするために、翻訳通りの説明になっていない部分や、僕自身が調べて追加説明してある部分があります。
- 公式に書かれていることを全て書いていませんし、公式の見解と一致しているとは限りません。
※間違え等あればご連絡くださいm(_ _)m
なお、このチュートリアルは、ReactやJavaScriptの基本を理解していることが前提になっているので、学習したことがなければ「React Foundations」という記事や下記の動画や書籍で体系的にReactを学んでから行うことをお勧めします!
(僕も使いました)
動画
【2023年最新】React(v18)完全入門ガイド|Hooks、Next.js、Redux、TypeScript書籍
目次
環境・バージョン
- Mac OS
- Node.js 20.9.0(18よりも新しいものである必要がある)
- VSCode
Chapter 1(Getting Started)
新しいプロジェクトの作成(Creating a new project)
まずは下記のコマンドを使い、任意の場所にプロジェクトを作ります。
$ pwd
/Users/user_name/Desktop/
# ここではDesktopに「nextjs-tutorial」というフォルダ名でプロジェクトを作成
$ npx create-next-app@latest nextjs-tutorial --use-npm --example "https://github.com/vercel/next-learn/tree/main/dashboard/starter-example"
下記のような質問があるので、それぞれ選択してエンターキーを押します。
- Would you like to use TypeScript?(プロジェクトに「TypeScript」を導入するかとどうか) → Yes
- Would you like to use ESLint?(プロジェクトに「ESLint」を導入するかとどうか) → Yes
- Would you like to use Tailwind CSS?(プロジェクトに「Tailwind CSS」を導入するかとどうか) → Yes
- Would you like to use
src/
directory?(プロジェクトでsrc/ディレクトリを使うかどうか)→ No - Would you like to use App Router? (recommended)(プロジェクトでApp Routerを使うかどうか(推奨されている)) → Yes
- Would you like to customize the default import alias (@/*)?(デフォルトのインポートエイリアスをカスタマイズするかどうか)→ No
それぞれの詳しい意味はこちら記事を参照するとよさそうです。→(「create-next-appで訊かれていること」)
「Success! Created …」との表示が出ればプロジェクトができています。
プロジェクトを見てみる(Exploring the project)
出来上がったプロジェクトをVSCodeでみてみましょう。
$ cd nextjs-tutorial
nextjs-tutorial $ code .
既にいくつかのファイルが出来上がっていました。
どうやらこのチュートリアルでは「Next.jsの主な機能を学習する」もののようです。
なのでスタイリングなどは既に済まされている状態から始めるとのこと。
下記がプロジェクト内のそれぞれのディレクトリやファイルの説明です。
- /app:ルートディレクトリ
- /app/lib:再利用可能な関数やデータ取得関数が入っているディレクトリ
- /app/ui:スタイリングされた(デザインができている)UIコンポーネントが入っているディレクトリ
- /public:画像など静的なファイルが入るディレクトリ
- /scripts/:データベースにデータを設定するためのファイルが入っているディレクトリ(後の章で使う)
- Config Files:ルートディレクトリにある「next.config.js」などの構成ファイルはcreate-next-appを使用して新しいプロジェクトを作成すると事前構成されるもの。今回のコースでは変更しなくてOK。
続いて、TypeScriptを導入しているので(「create next app」をした時にTypeScriptを使うか聞かれます)チュートリアルでおすすめされていた「Prisma」というNode.jsの「ORM(Object Relational Mapper)」を導入しておきます。
※「Prisma」や「ORM」とはなんぞや?という方は調べるなり、こちらの記事をご覧ください→( 「Prismaの導入とメリットを考える」)
# インストール
nextjs-tutorial $ npm install @prisma/client
# 初期化
nextjs-tutorial $ npx prisma init
上記を実行すると「.env」と「prisma/schema.prisma」ができるかと思います。
これでPrismaの導入はOKそうです!
※データベースを使うときに使用するものなので、実際に使うのは後のチャプターだと思われます。
開発サーバーの実行(Running the development server)
続いて、開発サーバーを実行します。
nextjs-tutorial $ npm i
nextjs-tutorial $ npm run dev
> dev
> next dev
▲ Next.js 14.0.0
- Local: http://localhost:3000
✓ Ready in 4.4s
○ Compiling /page ...
✓ Compiled /page in 2.3s (438 modules)
✓ Compiled /not-found in 205ms (443 modules)
Reload env: .env
✓ Compiled in 337ms (438 modules)
起動したのち「http://localhost:3000/」を開いて、下の画像のようなページが表示されればOKです。
Chapter 2(CSS Styling)
Chapter2で行っていくことの概略は下記のとおりです。
Currently, your home page doesn’t have any styles. Let’s look at the different ways you can style your Next.js application.
(現在、ホームページにはスタイルがありません。 Next.js アプリケーションをスタイル設定するさまざまな方法を見てみましょう。)
Learn Next.js: CSS Styling | Next.js(https://nextjs.org/learn/dashboard-app/css-styling)
Global styles
「/app/ui」フォルダ内にある「global.css」は下記を設定するのに適しているファイルです。
- リセットCSS
- サイト全体で適応させたいスタイル
「global.css」はアプリケーション内の全てのコンポーネントにインポートできますが、基本的には最上位のコンポーネント(Next.jsでは「layout.tsx」)に設定することがおすすめです。
「/app/layout.tsx」に下記のコードを追加します。
import '@/app/ui/global.css'; // 追加
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="en">
<body>{children}</body>
</html>
);
}
ファイルを保存後、開発サーバーを起動している状態であれば下の画像のようなページに変わっていればOKです。
CSSを書いていないにも関わらず、スタイルが反映されたのは、「global.css」に下記が書かれているためです。
@tailwind base;
@tailwind components;
@tailwind utilities;
これは「Tailwind.css」の設定です。
Tailwind
Tailwind.cssはJSX内に直接ユーティリティクラスを書くことで、開発を高速化するCSSフレームワークです。
Taiilwind.cssを使うメリットは下記です。
- スタイルの衝突が起きない(要素に直接スタイルが当たるようになるから)
- CSSファイルを個別に管理しなくて良くなる(global.cssに上記の設定を書くだけで良くなるから)
- アプリケーションが大きくなることによるCSSのバンドルサイズの増大を気にしなくて良くなる(②によるもの)
「/app/page.tsx」を見るとTailwind.cssのクラスが使われているのがわかります。
import AcmeLogo from '@/app/ui/acme-logo';
import Link from 'next/link';
export default function Page() {
return (
// These are Tailwind classes:
<main className="flex min-h-screen flex-col p-6">
<div className="flex h-20 shrink-0 items-end rounded-lg bg-blue-600 p-4 md:h-52">
// ...
)
}
試しに下記を「/app/page.tsx」に追加してTailwind.cssを実感してみましょう。
import AcmeLogo from '@/app/ui/acme-logo';
import Link from 'next/link';
export default function Page() {
return (
<main className="flex min-h-screen flex-col p-6">
<div className="flex h-20 shrink-0 items-end rounded-lg bg-blue-500 p-4 md:h-52">
{/* <AcmeLogo /> */}
</div>
<div className="mt-4 flex grow flex-col gap-4 md:flex-row">
<div className="flex flex-col justify-center gap-6 rounded-lg bg-gray-50 px-6 py-10 md:w-2/5 md:px-20">
// 追加部分
<div
className="h-0 w-0 border-b-[30px] border-l-[20px] border-r-[20px] border-b-black border-l-transparent border-r-transparent"
/>
// 追加部分
<p className={`text-xl text-gray-800 md:text-3xl md:leading-normal`}>
<strong>Welcome to Acme.</strong> This is the example for the{' '}
<a href="https://nextjs.org/learn/" className="text-blue-500">
Next.js Learn Course
</a>
, brought to you by Vercel.
</p>
)
}
※チュートリアルでは、上記コードを追加することで、どのような表示になるかのクイズが出されているので、考えて答えてみてください!
CSS Modules
従来のCSSを使いたい場合や、CSSをJSXから分けて書きたい場合は「CSS Modules」が代わりの手段となります。
CSS Modulesを使うと、コンポーネントごとに一意のクラス名を自動的に作成されるので、スタイルの衝突が起きづらくなります。
ここではCSS Modulesを使って「『Global styles』について」の最後のクイズと同じ形を作ります。
「/app/ui」に「home.module.css」という名前で新しいファイルを作り、下記のCSSを記述します。
.shape {
height: 0;
width: 0;
border-bottom: 30px solid black;
border-left: 20px solid transparent;
border-right: 20px solid transparent;
}
そして、下記のように「/app/page.tsx」で「home.module.css」をインポートし、tailwidのクラス名を「styles.shape」と書き換えます。
// 追加
import styles from '@/app/ui/home.module.css';
import AcmeLogo from '@/app/ui/acme-logo';
import Link from 'next/link';
export default function Page() {
return (
<main className="flex min-h-screen flex-col p-6">
<div className="flex h-20 shrink-0 items-end rounded-lg bg-blue-500 p-4 md:h-52">
{/* <AcmeLogo /> */}
</div>
<div className="mt-4 flex grow flex-col gap-4 md:flex-row">
<div className="flex flex-col justify-center gap-6 rounded-lg bg-gray-50 px-6 py-10 md:w-2/5 md:px-20">
// 変更部分
<div
className={styles.shape}
/>
// 変更部分
<p className={`text-xl text-gray-800 md:text-3xl md:leading-normal`}>
<strong>Welcome to Acme.</strong> This is the example for the{' '}
<a href="https://nextjs.org/learn/" className="text-blue-500">
Next.js Learn Course
</a>
, brought to you by Vercel.
</p>
)
}
まったく同じ表示になっているはずです。
「Tailwind.css」と「CSS Modules」はNext.jsでスタイリングする一般的な方法であり、どちらを選択するかは好みによります。また両方使うことも可能です。
※このチュートリアルではこの後はTailwind.cssを使うので、「CSS Modules」を試すために書いたコードやファイルは削除してOKです。
clsx(Using the clsx Library to toggle class names)
状態や条件によって、スタイルを変更させる必要がある場合、「clsx」というライブラリを使えば簡単にクラス名を切り替えることができます。
ここでは基本的な使い方だけ紹介します。
例えば、下記の条件の「InvoiceStatusコンポーネント」を作成します。
- 状態は「pending」と「paid」
- 「paid」の場合、緑色
- 「pending」の場合、グレー
下記のように「clsx」を使って、条件付きでクラス名を適用できます。
import clsx from 'clsx';
export default function InvoiceStatus({ status }: { status: string }) {
return (
<span
className={clsx(
'inline-flex items-center rounded-full px-2 py-1 text-sm',
{
'bg-gray-100 text-gray-500': status === 'pending',
'bg-green-500 text-white': status === 'paid',
},
)}
>
// ...
)}
その他のスタイル方法(Other styling solutions)
下記でスタイリングすることも可能です。
- Sass
- styled-jsx、styled-components、emotionといったCSS-in-JS
詳細はNext.jsのCSSのドキュメントを見てください。
Chapter 3(Optimizing Fonts and Images)
カスタムフォントとヒーロー画像(トップページのメインビジュアル)を追加していきます。
なぜフォントを最適化するのか?(Why optimize fonts?)
結論:Next.jsでカスタムフォント例えば「Google fonts」や「Adobe Fonts」のことだと思われる)を使用する場合は、パフォーマンスが良くなるから「next/font」モジュールを使用を推奨している。
プロジェクトでカスタムフォント(例えば「Google fonts」や「Adobe Fonts」のことだと思われる)を使用すると、フォントのファイルをフェッチ(取得)してロードする(読み込む)必要がある場合、パフォーマンスに影響を与える可能性があります。
「Cumulative Layout Shift」というGoogleがウェブサイトのパフォーマンスを評価する指標があります。フォントの場合、ブラウザが最初にフォールバックフォント、またはシステムフォントでテキストをレンダリングし、カスタムフォントを読み込み、カスタムフォントに置き換える時にレイアウトシフトが発生します。それにより、テキストのサイズや間隔、レイアウトが変更され、周囲の要素が移動する可能性があります。(チュートリアルのサイトに載っている画像を見るとフォントが置き換わるとズレる(レイアウトシフトが起きる)というのがわかりやすいかと思います。)
Next.jsは、「next/font」モジュールを使用すると、アプリケーション内のフォントを自動的に最適化してくれます。「next/font」モジュールはプロジェクトのビルド時にフォントのファイルをダウンロードします。そして、フォントのファイルを他の静的なアセットとと一緒にホスト(サーバーに置く)します。つまり、ユーザーがアプリケーションにアクセスするときに、パフォーマンスに影響するフォントのためのネットワークリクエストがなくなるということです。
アプリのベースとなるフォントを追加する(Adding a primary font)
どのように動くかを見るために、Googleフォントをアプリケーションに追加します。
下記のように「/app/ui」フォルダに「fonts.ts」ファイルを作成します。(今回作る「fonts.ts」はアプリ全体で使用されるフォントを定義するファイル)
「Inter」フォントを 「next/font/google」モジュールからインポートします。(アプリケーションの主要なフォントになります)
import { Inter } from 'next/font/google';
そして、ロードするサブセット(フォントの一部)を下記のように指定します。(ここでは「latin」)
※Googleフォントのサブセットを指定せずにロードすると、例えばここでは「Inter」フォントの全てを(「latin」以外にもあるっぽい(詳しくはここを参照))ロードすることになり、容量が大きくなってしまう。そのためサブセット設定をして「Inter」フォントの中でも使う一部をロードしているということのようです。(僕もサブセットの理解が若干曖昧です)
import { Inter } from 'next/font/google';
export const inter = Inter({ subsets: ['latin'] }); // 追加部分
最後に、「/app/layout.tsx」にinterをインポートして、body要素のクラスに設定をします。
import '@/app/ui/global.css';
import { inter } from '@/app/ui/fonts'; //追加 部分
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="en">
<body className={`${inter.className} antialiased`}>{children}</body> // 変更部分
</html>
);
}
これでアプリケーション全体にフォントが適用されます。(特定の要素に追加することも可能)
加えて、Tailwindの「antialiased」クラスをbody要素に追加しておきます。
必須ではないですが、つけておくと文字を滑らかにしてくれます!
フォントが描画されるときのアンチエイリアス(画面上で表示される輪郭を色の濃淡などを用いて滑らかにする処理)の適用を制御するプロパティ
例えばアニメーションが効いているフォントがピクピクするような不具合は下記設定で直る可能性があるそうです。
font-smoothing: antialiased; (Tailwindでは「antialiased」クラスをつければOK)
参考させてもらった記事
練習問題:セカンダリー(アプリの特定の場所に適応させるもの的な意味な気がする)フォントを追加する(Practice: Adding a secondary font)
ご自身で考えて「font.ts」ファイルに「Lusitana」フォントを追加するコードを書いて、「/app/page.tsx」のp要素に設定してください。サブセットは前(「Inter」フォント)と同じように加えてください。(font weightのオプションも設定する必要があります。)
※下記が答えになります。
import { Inter, Lusitana } from 'next/font/google';
export const inter = Inter({ subsets: ['latin'] });
export const lusitana = Lusitana({
weight: ['400', '700'],
subsets: ['latin'],
});
import AcmeLogo from '@/app/ui/acme-logo';
import { ArrowRightIcon } from '@heroicons/react/24/outline';
import { lusitana } from '@/app/ui/fonts';
export default function Page() {
return (
// ...
<p
className={`${lusitana.className} text-xl text-gray-800 md:text-3xl md:leading-normal`}
>
<strong>Welcome to Acme.</strong> This is the example for the{' '}
<a href="https://nextjs.org/learn/" className="text-blue-500">
Next.js Learn Course
</a>
, brought to you by Vercel.
</p>
// ...
);
}
コメントアウトになっている「<AcmeLogo />」コンポーネントも「Lusitana」フォントを使うのでコメントアウトを外しておきます。
// ...
export default function Page() {
return (
<main className="flex min-h-screen flex-col p-6">
<div className="flex h-20 shrink-0 items-end rounded-lg bg-blue-500 p-4 md:h-52">
<AcmeLogo />
{/* ... */}
</div>
</main>
);
}
なぜ画像を最適化するのか?(Why optimize images?)
結論:通常のマークアップでは下記を考慮して自分で設定する必要があります。それらを自動的に最適化してくれる「next/images」コンポーネントを使うのをNext.jsでは推奨しています。
- レスポンシブ対応
- デバイス毎の画像サイズの設定
- 画像読み込み時の崩れ(フォントと同じく適切な設定がないとレイアウトシフトが発生する)
- 遅延読み込み
Next.jsでは、アプリで使いたい画像などの静的なファイルを「/public」に置きます。
そして、下記のように「<Image>」コンポーネントを使って読み込ませるのを推奨しています。(「/app/page.tsx」に追加しましょう)
import AcmeLogo from '@/app/ui/acme-logo';
import { lusitana } from '@/app/ui/fonts';
import Image from 'next/image';
export default function Page() {
return (
// ...
<div className="flex items-center justify-center p-6 md:w-3/5 md:px-28 md:py-12">
{/* Add Hero Images Here */}
<Image
src="/hero-desktop.png"
width={1000}
height={760}
className="hidden md:block"
alt="Screenshots of the dashboard project showing desktop and mobile versions"
/>
</div>
//...
);
}
<Image>コンポーネントの設定としては下記の通りです。(普通のimgタグとほぼ同じ)
- src:表示させたいファイルのパスを設定
- width:表示させる画像の幅(px)を設定(レイアウトのずれを避けるために表示させる画像の幅を設定するのがおすすめ)
- height:表示させる画像の高さ(px)を設定(レイアウトのずれを避けるために表示させる画像の高さを設定するのがおすすめ)
- alt:代替テキストを設定
※「width」と「height」は表示させたい画像と同じアスペクト比にする必要がある。
画面が下記のようになっていればOKです。
練習問題:モバイル用のヒーロー画像を追加する(Practice: Adding the mobile hero image)
ご自身で考えて、「/app.page.tsx」にモバイル用のヒーロー画像を表示するために、別の<Image>コンポーネントを下記の条件で追加してください。
- widthは560px、heightは620px
- モバイル画面で表示、デスクトップ画面で非表示(Tailwind.cssの「md」で出し分けをしている)
※下記が答えになります。
import AcmeLogo from '@/app/ui/acme-logo';
import { ArrowRightIcon } from '@heroicons/react/24/outline';
import { lusitana } from '@/app/ui/fonts';
import Image from 'next/image';
export default function Page() {
return (
// ...
<div className="flex items-center justify-center p-6 md:w-3/5 md:px-28 md:py-12">
{/* Add Hero Images Here */}
<Image
src="/hero-desktop.png"
width={1000}
height={760}
className="hidden md:block"
alt="Screenshots of the dashboard project showing desktop and mobile versions"
/>
// 追加部分
<Image
src="/hero-mobile.png"
width={560}
height={620}
className="block md:hidden"
alt="Screenshot of the dashboard project showing mobile version"
/>
// 追加部分
</div>
//...
);
}
Chapter 4(Creating Layouts and Pages)
Chapter4で行っていくことの概略は下記のとおりです。
So far, your application only has a home page. Let’s learn how you can create more routes with layouts and pages.
(これまでのところ、アプリケーションにはホームページのみがあります。 レイアウトとページを使用してさらに多くのルートを作成する方法を学びましょう。)
Learn Next.js: Creating Layouts and Pages | Next.js(https://nextjs.org/learn/dashboard-app/creating-layouts-and-pages)
ネストされたルーティング(Nested routing)
Next.jsでルーティングを設定するには「/app」の中にパスに合わせたフォルダと「page.tsx」ファイルを作成します。
「page.tsx」がそれぞれのパスのページを表示するファイルとなります。なお、既に「/app」に「page.tsx」があり、それがルートに「/」のページとなります。
例えば、ここでは「/app/dashboard/page.tsx」を作り、どのような動きになるかみていきます。
ダッシュボードページを作る(Creating the dashboard page)
export default function Page() {
return <p>Dashboard Page</p>;
}
これで「http://localhost:3000/dashboard」を確認すると下記のようなページが表示されるはずです。
「/app」フォルダの中に、「/ui」フォルダや「lib」フォルダなどがありますが、このフォルダ内に「page.tsx」がないため、ルーティングは機能しません。
つまり、ページに関係する他のコードも「/app」フォルダの中に置くことが可能です。(例えばテストコードも)
※上記の部分の説明の役に自身がなかったので下記を試してみました。
- 「http://localhost:3000/ui」にアクセスすると404ページが表示されました。
- 「/ui」の中に下記「page.tsx」を作成後再度「http://localhost:3000/ui」にアクセスすると「UI Page」というテキストが表示されました。
export default function Page() {
return <p>UI Page</p>;
}
つまり、ルーティングを機能させるには下記が必要という認識で良さそうです。
- パスに合わせたフォルダを作成
- そのフォルダ内に「page.tsx」を作成
練習問題:ダッシュボードの中のページを作る(Practice: Creating the dashboard pages)
「/app/dashboard」フォルダ内に下記の2つのページを作成してみましょう。
- 顧客ページ:「http://localhost:3000/dashboard/customers」にアクセスすると「<p>Customers Page</p>」が返ってくる
- 請求書ページ:「http://localhost:3000/dashboard/invoices」にアクセスすると「<p>Invoices Page</p>」が返ってくる
※下記が答えになります。
export default function Page() {
return <p>Customers Page</p>;
}
export default function Page() {
return <p>InvoicesPage</p>;
}
ダッシュボードのレイアウトの作成(Creating the dashboard layout)
Next.jsでは、複数ページの共通部分を、「layout.tsx」を使って作成できます。
ここでは、ダッシュボードにあるナビゲーションを作っていきます。
「/dashboard」フォルダ内に「layout.tsx」ファイルを作成し、下記のコードを書きましょう。
import SideNav from '@/app/ui/dashboard/sidenav';
export default function Layout({ children }: { children: React.ReactNode }) {
return (
<div className="flex h-screen flex-col md:flex-row md:overflow-hidden">
<div className="w-full flex-none md:w-64">
<SideNav />
</div>
<div className="flex-grow p-6 md:overflow-y-auto md:p-12">{children}</div>
</div>
);
}
上記コードは下記の処理を行っています。
- 「layout.tsx」にインポートするコンポーネント(ここでは「SideNav」)はレイアウトの一部になります。
- <Layout />コンポーネントは「children」プロップスを受け取り、それぞれのページで表示させる内容を変えることができます。
dashboardページ以下をそれぞれ見ると下の画像のようになっているはずです。
「http://localhost:3000/dashboard」
「http://localhost:3000/dashboard/invoices」
「http://localhost:3000/dashboard/customers」
3つのページを見るとわかるかとは思いますが、下記のことがわかりますね!(検証ツールで見るのも良いかも)
- サイドバーが同じ
- 「/app/dashboard/page.tsx」、「/app/dashboard/invoices/page.tsx」、「/app/dashboard/customers/page.tsx」の内容が「/app/dashboard/layout.tsx」の「children」部分に反映されており、その部分のみ内容が変わっている
ちなみに、この状態で「http://localhost:3000」にアクセスしても、表示は特に変わりなく「/app/dashboard/layout.tsx」の内容は反映されていませんね。
なので、「layout.tsx」は、ファイルが配置してあるフォルダとその配下の「page.tsx」のデザインの共通部分を効率よく書いておくことができるという理解で良いかと思います!
また、「layout.tsx」を使用する利点が下記のように書かれております。
One benefit of using layouts in Next.js is that on navigation, only the page components update while the layout won’t re-render. This is called partial rendering
Learn Next.js: Creating Layouts and Pages | Next.js(https://nextjs.org/learn/dashboard-app/creating-layouts-and-pages)
(Next.jsでレイアウトを使用する利点の1つは、ナビゲーション時にページコンポーネントのみが更新され、レイアウトは再レンダリングされないことです。これは部分レンダリングと呼ばれます。)
ルートレイアウト(Root layout)
「/app/layout.tsx」は「ルートレイアウト」と呼ばれ必須のファイルです。
ルートレイアウトはアプリ内の全てのページで適応されます。そのため、htmlタグやbodyタグの変更やメタデータの追加を「/app/layout.tsx」で行います。(メタデータの追加は後の章で解説)
終わりに
Chapter1〜Chapter4までを見てきました!
ブログにまとめつつ学ぶのは大変ですが、自分への定着度合いが高い気がしております。
次の記事ではChapter5〜Chapter8をまとめる予定です。
しばしお待ちを٩( ‘ω’ )و
(僕も使いました)
動画
【2023年最新】React(v18)完全入門ガイド|Hooks、Next.js、Redux、TypeScript書籍