| ページ一覧 | ブログ | twitter |  書式 | 書式(表) |

MyMemoWiki

差分

ナビゲーションに移動 検索に移動
9,533 バイト追加 、 2024年10月6日 (日) 02:44
[[React]]| [[MUI]] |
{{amazon|4815619484}}
=概要=*[https://ja.next-community-docs.dev/docs/app-router/getting-started/ Next.js Document]*[https://qiita.com/newbee1939/items/7ce919f9a1a7153582b8#:~:text=React%20Serv React Server ComponentsとApp Routerをそろそろちゃんと理解したい]
*Reactは、あくまでUI部分のみ
*本格的なアプリ開発には周辺領域を担うためのフレームワークが必要
**リソース組み込みの自動最適化
**CSSフレームワーク、Tailwind CSSへの標準対応
 
=導入=
npm run build
npm start
</pre>
===静的サイトとしてビルドした場合の実行===
*Prisma でのデータアクセスの処理がビルド時に実行され、その時点の静的な出力になる
<pre>
npm run build
npx serve@latest out
</pre>
 
====ビルド結果がクリーンされない====
*https://blog.unimoku.com/20201209
*/.next /out はビルド時に削除しても良い。
*デフォルトでクリーンされない
<pre>
rm -rf .next out
</pre>
*ルート定義不要、フォルダ階層に準じてリクエストパスとコンポーネント(.jsファイル)との対応関係が決まる
*page.jsはファイル名も固定でフォルダー構造だけでリクエストパスが決定される
*デフォルトで作成したコンポーネントがサーバーコンポーネントになる
*クライアントコンポーネントにするにはuse clientを記述する必要がある
=====アプリ共通の外枠=====
*[名前] : 単一パラメータ
*[...名前] : キャッチオールセグメント
*<nowiki>[[...名前]] </nowiki> : 省略可能なキャッチオールセグメント
{| class="wikitable" style="margin:auto"
|+ App Routerのルートパラメータ
|-
| /app/foo/[...keys]/page.js || /foo/aaa/bbb || { keys: ['aaa', 'bbb'] }
|-
| /app/bar/<nowiki>[[...keys]]</nowiki>/page.js || /bar || {}
|-
| 〃 || /bar/aaa/bbb || { keys: ['aaa', 'bbb'] }
|}
 
==Tailwind CSS==
*https://tailwindcss.com/
*ユーティリティファーストをコンセプトに開発されたCSSフレームワーク
*ユーティリティを組み合わせてデザインを作るので独自のスタイルを作りやすく細かな調整もしやすいメリット
*標準のサイズ、カラーなどは用意されている
 
[https://tailwindcsscheatsheet.com/ Cheat Sheet]
 
*Tailwind CSSによるスタイルを適用
 
<pre>
import "./globals.css";
:
 
&lt;ul className="fle bg-blue-600 mb-4 pl-2"&gt;...&lt;/ul&gt;
</pre>
 
==Prisma==
*JavaScriptアプリからデータベース操作を取り持つO/Rマッパー
===インストール===
*成功すると以下のファイルが生成される
**.env : 環境変数ファイル、gitignore に追加する
** prisma/schema.prisma : Prismaのスキーマファイル
 
sqliteでの構成例
<pre>
$ npm install prisma --save-dev
$ npx prisma init --datasource-provider sqlite
warn You already have a .gitignore file. Don't forget to add `.env` in it to not commit any private information.
</pre>
 
===データモデルの定義===
*prisma/schema.prisma に追記
<pre>
model reviews {
id String @id
title String
author String
price Int
publlisher String
published String
image String
read DateTime @default(now())
memo String
}
</pre>
 
*DBに反映
<pre>
$ npx prisma db push
</pre>
 
*Prisma Studio(Webベース管理ツール)で確認
<pre>
$ npx prisma studio
</pre>
 
 
*Error: @prisma/client did not initialize yet. Please run "prisma generate" and try to import it again.
<pre>
$ nps prisma generate
</pre>
<pre>
import { PrismaClient } from "@prisma/client";
</pre>
 
*Prisma Clientの利用
<pre>
import { PrismaClient } from "@prisma/client";
</pre>
 
==サーバーアクション==
*Next.js内蔵の仕組み
*ページコンポーネント、イベントハンドラー、&lt;form&lt;要素のaction属性などからサーバーコードを呼び出す仕組み
*サーバーとのやりとりに際し、fetchなどの非同期通信コードの不要となり、例えばコンポーネントからデータベースを操作するにも直感的なコードを記述できる
*現時点ではα版
 
===有効化===
 
next.config.[https://qiita.com/taisei-ide-lyd/items/f3673e913e8b658946a6#:~:text=%E6%8B%A1%E5%BC%B5%E5%AD%90%E3%81%8C.mjs%E3%81%A8. mjs]
<pre>
const nextConfig = {
experimental: {
serverActions: true
}
};
</pre>
 
=コンポーネントの処理=
*[https://ja.next-community-docs.dev/docs/app-router/building-your-application/rendering/composition-patterns#:~:text=%E3%82%B5%E3%83%BC%E3%83%90%E3%83%BC%E3%81%A8%E3%82%AF%E3%83%A9%E3%82%A4%E3%82%A2%E3%83%B3 サーバーとクライアントの構成パターン]
 
==サーバー側で実行==
*Next.jsの基本はサーバー側でコンポーネントを処理
*[https://www.ey-office.com/blog_archive/2024/05/29/tried-running-react-server-component-in-a-production-environment-and-got-a-little-hooked/ 本番環境で動かす]
*メリット
**サーバーリソースの活用
**ダウンロードコードサイズの最小化
**機密情報(サクセストークンなど)の管理
*クライアントに依存する操作には対応していない
**State関連操作(useState,useReducer,useEffectなど)
**イベントリスナー(onXxxxx)
**ブラウザAPIアクセス
**上記を伴うカスタムフック
**クラスコンポーネント利用
 
==クライアント側で実行==
*ファイルの先頭に、'use client'ディレクティブを記述することでコンポーネントをクライアント側で実行可
 
==静的サイト==
*[https://zenn.dev/hiromu617/articles/1ed6811dc6cf26 静的サイトの生成]
*静的エクスポートを有効にすることによりビルド時の生成物がNode.jsサーバーを必要としないものとなる
<pre>
const nextConfig = {
:
output: 'export'
}
</pre>
*この機能を有効にすることで、ridirectsやmiddlewareなどのサーバーを必要とする一部機能が使えなくなります
*動的レンダリングも一切できなくなってしまうのでこの機能を有効にするかはアプリケーションの性質を考慮して検討
 
=実装=
 
==ルートレイアウト==
===アプリ内のリンクにはLinkコンポーネントを利用===
 
<pre>
import Link from "next/link";
</pre>
 
規定で以下のようなコンポーネントが用意されており、アプリ内リソースを効率的に利用できる
{| class="wikitable"
|+ コンポーネント
|-
! コンポーネント !! 概要
|-
| &lt;Link&gt; || リンクを生成
|-
| &lt;Script&gt; || スクリプトのロード
|-
| &lt;Image&gt; || 画像を表示
|}
 
===メタデータ===
*メタデータを定義しておくことで、個々のページに適切なヘッダーなどを埋め込める
*複数箇所で宣言された場合、シャローマージされる
<pre>
export const metadata: Metadata = {
title: "Reading Recorder",
description: "自分が読んだ書籍の記録を残す",
};
</pre>
 
*generateMetadata関数を利用しデータベースなどから取得した結果を元に動的に生成も可能
<pre>
export async function generateMetadata({ params, searchParams }) {
:
return {
title : result.title,
:
}
}
</pre>
 
===Route Segment Config===
*https://nextjs.org/docs/app/api-reference/file-conventions/route-segment-config
*レイアウト、ページ単位の設定
*あらかじめ決められた名前の変数をエクスポートしておくことで、個別の設定を施せる
*force-dynamic : 極力キャッシュを無効にし、ページを動的に描画しようとする
 
<pre>
export const dynamic = 'force-dynamic'
</pre>
 
=フォント=
*Googleフォント(無償フォントのディレクトリサービス)を有効化
*具体的なフォントはGoogleフォントから自由に選択できるが一般的にはバリアブルフォント推奨(下例ではInconsolata)
*フォントはファイルサイズが大きいので、subsetで利用する文字のみ取り出す
*fnc.className でフォントを適用できる
<pre>
import { Inconsolata } from 'next/font/google';
const fnt = Inconsolata({ subsets: ['latin'] });
 
:
&lt;body className={`${fnt.className}` }&gt;
</pre>
 
=MUI=
[[MUI]]
 
=外部サービスからのデータ取得=
*標準JavaScriptのfetchが拡張されている
*関数コンポーネントを非同期(async)とすることでコンポーネント配下でfetchメソッドを実行できる
*個々のfetch呼び出しに際して、キャッシュ/再取得ルールを指定できる
*コンポーネント改装間で同一データを取得の場合、リクエストの重複を除去
<pre>
fetch('https://...", { cache: 'force-cache' }); // 無制限にキャッシュ
fetch('https://..."); // 無制限にキャッシュ
fetch('https://...", { cache: 'no-store' }); // 常にデータを取得
fetch('https://...", { cache: 'revalidate: 10' }); // 10秒以上でデータを再取得
</pre>
 
=Objects=
==useRef==
*https://ja.react.dev/reference/react/useRef
*ref を変更しても、再レンダーはトリガされないということです。このことから、ref は、出力されるコンポーネントの外見に影響しないデータを保存するのに適しています
*ref を使用することで、次のことが保証されます。
*レンダーを跨いで情報を保存できます(通常の変数は、レンダーごとにリセットされます)。
*変更しても再レンダーはトリガされません(state 変数は、変更すると再レンダーがトリガされます)。
*保存された情報は、コンポーネントのインスタンスごとに固有です(コンポーネントの外側で定義された変数は、コンポーネントのインスタンス間で共有されます)。
*[https://zenn.dev/tns_00/articles/react-typescript-form-error-of-value TypeScriptでエラーの場合]
 
<pre>
import { useRef } from 'react';
 
const txtKeyword = useRef<HTMLInputElement>(null);
console.log(`txtKeyword.current.value:${txtKeyword.current?.value}`);
:
&lt;input type="text" ref={txtKeyword} ../&gt;
</pre>
 
=Tips=
 
==リモートホストからの画像表示を許可する==
*next.config.mjs
<pre>
const nextConfig = {
 
:
 
images: {
remotePatterns: [
{
hostname: 'books.google.com'
}
]
}
};
</pre>

案内メニュー