<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="ja">
	<id>https://www.typea.info/tips_/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Piroto</id>
	<title>MyMemoWiki - 利用者の投稿記録 [ja]</title>
	<link rel="self" type="application/atom+xml" href="https://www.typea.info/tips_/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Piroto"/>
	<link rel="alternate" type="text/html" href="https://www.typea.info/tips_/index.php/%E7%89%B9%E5%88%A5:%E6%8A%95%E7%A8%BF%E8%A8%98%E9%8C%B2/Piroto"/>
	<updated>2026-06-14T02:44:57Z</updated>
	<subtitle>利用者の投稿記録</subtitle>
	<generator>MediaWiki 1.34.0</generator>
	<entry>
		<id>https://www.typea.info/tips_/index.php?title=Mac&amp;diff=35371</id>
		<title>Mac</title>
		<link rel="alternate" type="text/html" href="https://www.typea.info/tips_/index.php?title=Mac&amp;diff=35371"/>
		<updated>2024-12-31T00:57:19Z</updated>

		<summary type="html">&lt;p&gt;Piroto: /* Appleシリコンを搭載したMacをセーフモードで起動する */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;| [[Xcode]] | [[Swift]] | [[SwiftUI]] | [[Ubuntu]] | [[Docker]] |&lt;br /&gt;
==[[Mac]]==&lt;br /&gt;
&lt;br /&gt;
{{amazon|4800712785}}&lt;br /&gt;
&lt;br /&gt;
*[[Mac 使い方メモ]]&lt;br /&gt;
&lt;br /&gt;
===基本===&lt;br /&gt;
----&lt;br /&gt;
====hostnameを変更====&lt;br /&gt;
# メニュー - 「システム環境設定」 - 「共有」&lt;br /&gt;
# 「編集」をクリックし、新しいローカルホスト名を入力&lt;br /&gt;
&lt;br /&gt;
====シェルをbashに変更====&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
% cat /etc/shells&lt;br /&gt;
/bin/bash&lt;br /&gt;
/bin/csh&lt;br /&gt;
    :&lt;br /&gt;
% chsh -s /bin/bash&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===キーバインド===&lt;br /&gt;
----&lt;br /&gt;
====バックスラッシュの入力====&lt;br /&gt;
----&lt;br /&gt;
*option + ¥&lt;br /&gt;
&lt;br /&gt;
====日本語入力====&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
*Windows風キー入力&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| キー&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| 意味&lt;br /&gt;
|-&lt;br /&gt;
| ctrl + u&lt;br /&gt;
| ひらがな&lt;br /&gt;
|-&lt;br /&gt;
| ctrl + i&lt;br /&gt;
| カタカナ&lt;br /&gt;
|-&lt;br /&gt;
| ctrl + o&lt;br /&gt;
| 半角英数&lt;br /&gt;
|-&lt;br /&gt;
| ctrl + p&lt;br /&gt;
| 全角英数&lt;br /&gt;
|-&lt;br /&gt;
| ctrl + k&lt;br /&gt;
| 選択中の文節を縮める&lt;br /&gt;
|-&lt;br /&gt;
| ctrｌ + l&lt;br /&gt;
| 選択中の文節を伸ばす&lt;br /&gt;
|-&lt;br /&gt;
| 範囲選択し、かな×2回&lt;br /&gt;
| 再変換&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
=====日本語入力中に数字を半角入力する=====&lt;br /&gt;
*環境設定 ー キーボード ー 日本語ローマ字入力 ー 入力ソース ー 「数字を全角入力」のチェックをOFF&lt;br /&gt;
&lt;br /&gt;
====ツール====&lt;br /&gt;
=====画面キャプチャ=====&lt;br /&gt;
ctrl 長押し＋以下を行うと、クリップボードにコピーされる&lt;br /&gt;
&lt;br /&gt;
*[shift]キー＋[command]キー＋[3]キーで画面全体を撮る&lt;br /&gt;
*[shift]キー＋[command]キー＋[4]キーで画面の一部を撮る&lt;br /&gt;
*[shift]キー＋[command]キー＋[4]キー→ [Space]キーでウィンドウ&lt;br /&gt;
*[shift]キー＋[command]キー＋[5]キー→オプション&lt;br /&gt;
&lt;br /&gt;
=====動画キャプチャ=====&lt;br /&gt;
*音声を取得するには[https://github.com/mattingalls/Soundflower/releases Soundflower]をインストールし、shift + command + 5 のオプションから入力を指定&lt;br /&gt;
&lt;br /&gt;
====キーボード記号====&lt;br /&gt;
----&lt;br /&gt;
*https://support.apple.com/ja-jp/guide/mac-help/cpmh0011/mac&lt;br /&gt;
[[File:Mac_keyboard_sign1.png|400px]]&lt;br /&gt;
[[File:Mac_keyboard_sign2.png|400px]]&lt;br /&gt;
&lt;br /&gt;
===Finder===&lt;br /&gt;
----&lt;br /&gt;
====ショートカット====&lt;br /&gt;
*http://inforati.jp/apple/mac-tips-techniques/system-hints/how-to-use-mac-finder-with-keyboard-shortcut.html&lt;br /&gt;
=====実行(command+o)=====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=====ファイルのカット＆ペースト=====&lt;br /&gt;
# command+c&lt;br /&gt;
# option+command+v&lt;br /&gt;
&lt;br /&gt;
====サイドバーにホームディレクトリを表示====&lt;br /&gt;
----&lt;br /&gt;
*メニューー環境設定ーサイドバー&lt;br /&gt;
====ターミナルから開く====&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ open .&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====場所を指定して開く====&lt;br /&gt;
----&lt;br /&gt;
*Command + G で場所を入力&lt;br /&gt;
====システムフォルダを開く====&lt;br /&gt;
----&lt;br /&gt;
*一時的&lt;br /&gt;
**Command + G で場所を入力&lt;br /&gt;
*継続的&lt;br /&gt;
**以下のコマンドを入力、リブート&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
defaults write com.apple.Finder AppleShowAllFiles YES&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
[[File:Finder_show_all.png|400px]]&lt;br /&gt;
&lt;br /&gt;
===高速化手法===&lt;br /&gt;
----&lt;br /&gt;
====メモリを解放====&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ sudo purge&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
*https://commte.net/6966&lt;br /&gt;
=====セーフブートモードで起動=====&lt;br /&gt;
----&lt;br /&gt;
セーフブートモードで起動すると、ディレクトリのメンテナンスと膨大な量のシステムキャッシュファイルを削除してくれます。通常はShiftキーを押しながら起動&lt;br /&gt;
&lt;br /&gt;
=====Macmini reset=====&lt;br /&gt;
*システム終了します。&lt;br /&gt;
*電源コードを抜いて、15秒間待ちます。&lt;br /&gt;
*電源コードを差し直して、5秒間待ちます。&lt;br /&gt;
*電源ボタンを押して起動します。&lt;br /&gt;
&lt;br /&gt;
====パフォーマンス改善====&lt;br /&gt;
*https://blog.avast.com/jp/guide-to-speeding-and-cleaning-mac&lt;br /&gt;
=====ディスクスキャン=====&lt;br /&gt;
*スキャンを実行するには、メニュー バーの [移動] をクリックして [ユーティリティ] に移動します。ここで [ディスク ユーティリティ] をクリックします。メイン ハード ディスクを選択して [First Aid] をクリックします。&lt;br /&gt;
====SMC のリセット====&lt;br /&gt;
----&lt;br /&gt;
*着脱不能バッテリーを搭載した MacBook の場合、SMC をリセットするには、Mac を完全にシャットダウンする必要があります。次に、Mac の電源がオフになっている間に、キーボードの左側の [SHIFT] + [CONTROL] + [OPTION] キーを押しながら電源ボタンを押します。これらすべてのキーを 10 秒間押し続けます（指がつらないように気を付けてください）。キーを離し、通常どおりに Mac の電源を入れます。&lt;br /&gt;
&lt;br /&gt;
===ディスク容量を増やす===&lt;br /&gt;
----&lt;br /&gt;
====このMacストレージを管理====&lt;br /&gt;
----&lt;br /&gt;
*https://support.apple.com/ja-jp/HT206996&lt;br /&gt;
*Apple メニュー  &amp;gt;「この Mac について」の順に選択し、「ストレージ」をクリックします。&lt;br /&gt;
*棒グラフの各セグメントは、ファイルのカテゴリごとのストレージ使用量の概算値を表しています。各セグメントの上にポインタを置くと、詳細情報が表示されます。&lt;br /&gt;
*ストレージ管理のウインドウには、ストレージを最適に使うための対策が「おすすめ」として表示されます&lt;br /&gt;
====セーフブートモードで起動====&lt;br /&gt;
----&lt;br /&gt;
[https://support.apple.com/ja-jp/guide/mac-help/mh21245/mac セーフブートモードで起動]すると、ディレクトリのメンテナンスと膨大な量のシステムキャッシュファイルを削除してくれます。通常はShiftキーを押しながら起動&lt;br /&gt;
&lt;br /&gt;
=====Appleシリコンを搭載したMacをセーフモードで起動する=====&lt;br /&gt;
#Macで、アップルメニュー  ＞「システム終了」と選択します。&lt;br /&gt;
#Macが完全にシステム終了するまで待ちます。Macが完全にシステム終了すると画面が黒くなり、すべてのランプ（Touch Barのランプを含む）が消えます。&lt;br /&gt;
#「起動オプションを読み込み中」と表示されるまで、Macの電源ボタンを押したままにします。&lt;br /&gt;
#ボリュームを選択します。&lt;br /&gt;
#Shiftキーを押し続ける！ -&amp;gt;「セーフモードで続ける」をクリックします。&lt;br /&gt;
#コンピュータは自動的に再起動します。ログインウインドウが表示されたら、メニューバーに「セーフブート」と表示されます。&lt;br /&gt;
&lt;br /&gt;
=====Intelプロセッサを搭載したMacをセーフモードで起動する=====&lt;br /&gt;
#Macを起動または再起動したらすぐにShiftキーを押したままにして、ログインウインドウが表示されたら放します。&lt;br /&gt;
#Macにログインします。&lt;br /&gt;
#もう一度ログインするように求められる場合があります。&lt;br /&gt;
#最初または2番目のログインウインドウのいずれかで、メニューバーに「セーフブート」と表示されます。&lt;br /&gt;
&lt;br /&gt;
====Homebrew====&lt;br /&gt;
*[https://www.typea.info/tips_/index.php/Node.js#Homebrew_.E3.82.A4.E3.83.B3.E3.82.B9.E3.83.88.E3.83.BC.E3.83.AB Homebrewのインストール]&lt;br /&gt;
*Homebrewのキャッシュ削除&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
$ brew cleanup&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===管理===&lt;br /&gt;
----&lt;br /&gt;
====Remote Desktop====&lt;br /&gt;
----&lt;br /&gt;
=====[http://typea.info/blg/glob/2020/01/macwindows10.html Macからホスト名でWindows10にリモートデスクトップ接続]=====&lt;br /&gt;
----&lt;br /&gt;
*[http://typea.info/blg/glob/2020/01/macwindows10.html Macからホスト名でWindows10にリモートデスクトップ接続]&lt;br /&gt;
&lt;br /&gt;
=====IME切り替え=====&lt;br /&gt;
----&lt;br /&gt;
*[[Windows]]にリモート接続し、IMEを切り替えるショートカットをIMEの設定から有効にする&lt;br /&gt;
[[File:mac_remote_win_ime.png|400px]]&lt;br /&gt;
=====バックスラッシュ入力できない問題=====&lt;br /&gt;
* https://qiita.com/KNaito/items/e4436cb73f9ff257394d&lt;br /&gt;
* https://blog.tsukumijima.net/article/mac-windows-keyboard-tweek/&lt;br /&gt;
* https://karabiner-elements.pqrs.org/&lt;br /&gt;
* https://karabiner-elements.pqrs.org/docs/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
bundle_identifiers&lt;br /&gt;
* https://karabiner-elements.pqrs.org/docs/json/complex-modifications-manipulator-definition/conditions/frontmost-application/&lt;br /&gt;
*[https://www.typea.info/blog/index.php/2022/02/03/input_backslash_to_win_via_mac_remote_desktop/ MacリモートデスクトップからWindows¥入力]&lt;br /&gt;
&lt;br /&gt;
====SSHポートフォワーディング====&lt;br /&gt;
----&lt;br /&gt;
*ssh -L {localhostからアクセスするポート}:{踏み台経由でアクセスしたいサーバーアドレス} {踏み台となるサーバー}&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ ssh -L 10443:192.168.64.2:10443 hirotoyagi@delhi.local&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
*上記でSSH接続した状態で、localhost:ポート に接続する&lt;br /&gt;
&lt;br /&gt;
===画像===&lt;br /&gt;
----&lt;br /&gt;
====プレビューでトリミング====&lt;br /&gt;
----&lt;br /&gt;
トリミングを行いたい画像をダブルクリックすると、基本的にはプレビューが自動的に起動します。 この画像の上でクリックをしたまま、引っ張ると四角く範囲を選択することができます。 トリミングしたい部分で、クリックを離します。 選択範囲に問題がなければ、command+Kを押してトリミングすることができます。&lt;br /&gt;
====プレビューで透過画像を作成する====&lt;br /&gt;
[[File:instant_alpha.png|300px]]&lt;br /&gt;
&lt;br /&gt;
* command + x&lt;br /&gt;
*　範囲を切り取り、貼り付け&lt;br /&gt;
&lt;br /&gt;
===TIps===&lt;br /&gt;
----&lt;br /&gt;
====スリープ====&lt;br /&gt;
----&lt;br /&gt;
*option + command + メディア取り出し&lt;br /&gt;
&lt;br /&gt;
====古いOS用のアプリを入手する====&lt;br /&gt;
----&lt;br /&gt;
*https://filehippo.jp/&lt;br /&gt;
&lt;br /&gt;
=====[https://filehippo.jp/mac/download_microsoft_remote_desktop/ Microsoft Remote Desktop]=====&lt;br /&gt;
=====[https://amzn.to/3vl3F1R Kindle for mac]=====&lt;br /&gt;
&lt;br /&gt;
=====[https://developer.apple.com/download/more/ XCode]=====&lt;br /&gt;
&lt;br /&gt;
====treeコマンドのインストール====&lt;br /&gt;
&lt;br /&gt;
 brew install tree&lt;br /&gt;
&lt;br /&gt;
===トラブルシュート===&lt;br /&gt;
----&lt;br /&gt;
====Xcodeがインストール中で終わらない====&lt;br /&gt;
----&lt;br /&gt;
*いったんアンインストールしてから、AppStoreからインストール&lt;br /&gt;
&lt;br /&gt;
===ツールインストール===&lt;br /&gt;
*[[Java SE]]&lt;br /&gt;
*[[Node.js]]&lt;br /&gt;
*[[Dart]]&lt;br /&gt;
*[[Flutter]]&lt;/div&gt;</summary>
		<author><name>Piroto</name></author>
		
	</entry>
	<entry>
		<id>https://www.typea.info/tips_/index.php?title=Mac&amp;diff=35370</id>
		<title>Mac</title>
		<link rel="alternate" type="text/html" href="https://www.typea.info/tips_/index.php?title=Mac&amp;diff=35370"/>
		<updated>2024-12-31T00:49:18Z</updated>

		<summary type="html">&lt;p&gt;Piroto: /* Intelプロセッサを搭載したMacをセーフモードで起動する */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;| [[Xcode]] | [[Swift]] | [[SwiftUI]] | [[Ubuntu]] | [[Docker]] |&lt;br /&gt;
==[[Mac]]==&lt;br /&gt;
&lt;br /&gt;
{{amazon|4800712785}}&lt;br /&gt;
&lt;br /&gt;
*[[Mac 使い方メモ]]&lt;br /&gt;
&lt;br /&gt;
===基本===&lt;br /&gt;
----&lt;br /&gt;
====hostnameを変更====&lt;br /&gt;
# メニュー - 「システム環境設定」 - 「共有」&lt;br /&gt;
# 「編集」をクリックし、新しいローカルホスト名を入力&lt;br /&gt;
&lt;br /&gt;
====シェルをbashに変更====&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
% cat /etc/shells&lt;br /&gt;
/bin/bash&lt;br /&gt;
/bin/csh&lt;br /&gt;
    :&lt;br /&gt;
% chsh -s /bin/bash&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===キーバインド===&lt;br /&gt;
----&lt;br /&gt;
====バックスラッシュの入力====&lt;br /&gt;
----&lt;br /&gt;
*option + ¥&lt;br /&gt;
&lt;br /&gt;
====日本語入力====&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
*Windows風キー入力&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| キー&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| 意味&lt;br /&gt;
|-&lt;br /&gt;
| ctrl + u&lt;br /&gt;
| ひらがな&lt;br /&gt;
|-&lt;br /&gt;
| ctrl + i&lt;br /&gt;
| カタカナ&lt;br /&gt;
|-&lt;br /&gt;
| ctrl + o&lt;br /&gt;
| 半角英数&lt;br /&gt;
|-&lt;br /&gt;
| ctrl + p&lt;br /&gt;
| 全角英数&lt;br /&gt;
|-&lt;br /&gt;
| ctrl + k&lt;br /&gt;
| 選択中の文節を縮める&lt;br /&gt;
|-&lt;br /&gt;
| ctrｌ + l&lt;br /&gt;
| 選択中の文節を伸ばす&lt;br /&gt;
|-&lt;br /&gt;
| 範囲選択し、かな×2回&lt;br /&gt;
| 再変換&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
=====日本語入力中に数字を半角入力する=====&lt;br /&gt;
*環境設定 ー キーボード ー 日本語ローマ字入力 ー 入力ソース ー 「数字を全角入力」のチェックをOFF&lt;br /&gt;
&lt;br /&gt;
====ツール====&lt;br /&gt;
=====画面キャプチャ=====&lt;br /&gt;
ctrl 長押し＋以下を行うと、クリップボードにコピーされる&lt;br /&gt;
&lt;br /&gt;
*[shift]キー＋[command]キー＋[3]キーで画面全体を撮る&lt;br /&gt;
*[shift]キー＋[command]キー＋[4]キーで画面の一部を撮る&lt;br /&gt;
*[shift]キー＋[command]キー＋[4]キー→ [Space]キーでウィンドウ&lt;br /&gt;
*[shift]キー＋[command]キー＋[5]キー→オプション&lt;br /&gt;
&lt;br /&gt;
=====動画キャプチャ=====&lt;br /&gt;
*音声を取得するには[https://github.com/mattingalls/Soundflower/releases Soundflower]をインストールし、shift + command + 5 のオプションから入力を指定&lt;br /&gt;
&lt;br /&gt;
====キーボード記号====&lt;br /&gt;
----&lt;br /&gt;
*https://support.apple.com/ja-jp/guide/mac-help/cpmh0011/mac&lt;br /&gt;
[[File:Mac_keyboard_sign1.png|400px]]&lt;br /&gt;
[[File:Mac_keyboard_sign2.png|400px]]&lt;br /&gt;
&lt;br /&gt;
===Finder===&lt;br /&gt;
----&lt;br /&gt;
====ショートカット====&lt;br /&gt;
*http://inforati.jp/apple/mac-tips-techniques/system-hints/how-to-use-mac-finder-with-keyboard-shortcut.html&lt;br /&gt;
=====実行(command+o)=====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=====ファイルのカット＆ペースト=====&lt;br /&gt;
# command+c&lt;br /&gt;
# option+command+v&lt;br /&gt;
&lt;br /&gt;
====サイドバーにホームディレクトリを表示====&lt;br /&gt;
----&lt;br /&gt;
*メニューー環境設定ーサイドバー&lt;br /&gt;
====ターミナルから開く====&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ open .&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====場所を指定して開く====&lt;br /&gt;
----&lt;br /&gt;
*Command + G で場所を入力&lt;br /&gt;
====システムフォルダを開く====&lt;br /&gt;
----&lt;br /&gt;
*一時的&lt;br /&gt;
**Command + G で場所を入力&lt;br /&gt;
*継続的&lt;br /&gt;
**以下のコマンドを入力、リブート&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
defaults write com.apple.Finder AppleShowAllFiles YES&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
[[File:Finder_show_all.png|400px]]&lt;br /&gt;
&lt;br /&gt;
===高速化手法===&lt;br /&gt;
----&lt;br /&gt;
====メモリを解放====&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ sudo purge&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
*https://commte.net/6966&lt;br /&gt;
=====セーフブートモードで起動=====&lt;br /&gt;
----&lt;br /&gt;
セーフブートモードで起動すると、ディレクトリのメンテナンスと膨大な量のシステムキャッシュファイルを削除してくれます。通常はShiftキーを押しながら起動&lt;br /&gt;
&lt;br /&gt;
=====Macmini reset=====&lt;br /&gt;
*システム終了します。&lt;br /&gt;
*電源コードを抜いて、15秒間待ちます。&lt;br /&gt;
*電源コードを差し直して、5秒間待ちます。&lt;br /&gt;
*電源ボタンを押して起動します。&lt;br /&gt;
&lt;br /&gt;
====パフォーマンス改善====&lt;br /&gt;
*https://blog.avast.com/jp/guide-to-speeding-and-cleaning-mac&lt;br /&gt;
=====ディスクスキャン=====&lt;br /&gt;
*スキャンを実行するには、メニュー バーの [移動] をクリックして [ユーティリティ] に移動します。ここで [ディスク ユーティリティ] をクリックします。メイン ハード ディスクを選択して [First Aid] をクリックします。&lt;br /&gt;
====SMC のリセット====&lt;br /&gt;
----&lt;br /&gt;
*着脱不能バッテリーを搭載した MacBook の場合、SMC をリセットするには、Mac を完全にシャットダウンする必要があります。次に、Mac の電源がオフになっている間に、キーボードの左側の [SHIFT] + [CONTROL] + [OPTION] キーを押しながら電源ボタンを押します。これらすべてのキーを 10 秒間押し続けます（指がつらないように気を付けてください）。キーを離し、通常どおりに Mac の電源を入れます。&lt;br /&gt;
&lt;br /&gt;
===ディスク容量を増やす===&lt;br /&gt;
----&lt;br /&gt;
====このMacストレージを管理====&lt;br /&gt;
----&lt;br /&gt;
*https://support.apple.com/ja-jp/HT206996&lt;br /&gt;
*Apple メニュー  &amp;gt;「この Mac について」の順に選択し、「ストレージ」をクリックします。&lt;br /&gt;
*棒グラフの各セグメントは、ファイルのカテゴリごとのストレージ使用量の概算値を表しています。各セグメントの上にポインタを置くと、詳細情報が表示されます。&lt;br /&gt;
*ストレージ管理のウインドウには、ストレージを最適に使うための対策が「おすすめ」として表示されます&lt;br /&gt;
====セーフブートモードで起動====&lt;br /&gt;
----&lt;br /&gt;
[https://support.apple.com/ja-jp/guide/mac-help/mh21245/mac セーフブートモードで起動]すると、ディレクトリのメンテナンスと膨大な量のシステムキャッシュファイルを削除してくれます。通常はShiftキーを押しながら起動&lt;br /&gt;
&lt;br /&gt;
=====Appleシリコンを搭載したMacをセーフモードで起動する=====&lt;br /&gt;
#Macで、アップルメニュー  ＞「システム終了」と選択します。&lt;br /&gt;
#Macが完全にシステム終了するまで待ちます。Macが完全にシステム終了すると画面が黒くなり、すべてのランプ（Touch Barのランプを含む）が消えます。&lt;br /&gt;
#「起動オプションを読み込み中」と表示されるまで、Macの電源ボタンを押したままにします。&lt;br /&gt;
#ボリュームを選択します。&lt;br /&gt;
#Shiftキーを押したまま、「セーフモードで続ける」をクリックします。&lt;br /&gt;
#コンピュータは自動的に再起動します。ログインウインドウが表示されたら、メニューバーに「セーフブート」と表示されます。&lt;br /&gt;
&lt;br /&gt;
=====Intelプロセッサを搭載したMacをセーフモードで起動する=====&lt;br /&gt;
#Macを起動または再起動したらすぐにShiftキーを押したままにして、ログインウインドウが表示されたら放します。&lt;br /&gt;
#Macにログインします。&lt;br /&gt;
#もう一度ログインするように求められる場合があります。&lt;br /&gt;
#最初または2番目のログインウインドウのいずれかで、メニューバーに「セーフブート」と表示されます。&lt;br /&gt;
&lt;br /&gt;
====Homebrew====&lt;br /&gt;
*[https://www.typea.info/tips_/index.php/Node.js#Homebrew_.E3.82.A4.E3.83.B3.E3.82.B9.E3.83.88.E3.83.BC.E3.83.AB Homebrewのインストール]&lt;br /&gt;
*Homebrewのキャッシュ削除&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
$ brew cleanup&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===管理===&lt;br /&gt;
----&lt;br /&gt;
====Remote Desktop====&lt;br /&gt;
----&lt;br /&gt;
=====[http://typea.info/blg/glob/2020/01/macwindows10.html Macからホスト名でWindows10にリモートデスクトップ接続]=====&lt;br /&gt;
----&lt;br /&gt;
*[http://typea.info/blg/glob/2020/01/macwindows10.html Macからホスト名でWindows10にリモートデスクトップ接続]&lt;br /&gt;
&lt;br /&gt;
=====IME切り替え=====&lt;br /&gt;
----&lt;br /&gt;
*[[Windows]]にリモート接続し、IMEを切り替えるショートカットをIMEの設定から有効にする&lt;br /&gt;
[[File:mac_remote_win_ime.png|400px]]&lt;br /&gt;
=====バックスラッシュ入力できない問題=====&lt;br /&gt;
* https://qiita.com/KNaito/items/e4436cb73f9ff257394d&lt;br /&gt;
* https://blog.tsukumijima.net/article/mac-windows-keyboard-tweek/&lt;br /&gt;
* https://karabiner-elements.pqrs.org/&lt;br /&gt;
* https://karabiner-elements.pqrs.org/docs/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
bundle_identifiers&lt;br /&gt;
* https://karabiner-elements.pqrs.org/docs/json/complex-modifications-manipulator-definition/conditions/frontmost-application/&lt;br /&gt;
*[https://www.typea.info/blog/index.php/2022/02/03/input_backslash_to_win_via_mac_remote_desktop/ MacリモートデスクトップからWindows¥入力]&lt;br /&gt;
&lt;br /&gt;
====SSHポートフォワーディング====&lt;br /&gt;
----&lt;br /&gt;
*ssh -L {localhostからアクセスするポート}:{踏み台経由でアクセスしたいサーバーアドレス} {踏み台となるサーバー}&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ ssh -L 10443:192.168.64.2:10443 hirotoyagi@delhi.local&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
*上記でSSH接続した状態で、localhost:ポート に接続する&lt;br /&gt;
&lt;br /&gt;
===画像===&lt;br /&gt;
----&lt;br /&gt;
====プレビューでトリミング====&lt;br /&gt;
----&lt;br /&gt;
トリミングを行いたい画像をダブルクリックすると、基本的にはプレビューが自動的に起動します。 この画像の上でクリックをしたまま、引っ張ると四角く範囲を選択することができます。 トリミングしたい部分で、クリックを離します。 選択範囲に問題がなければ、command+Kを押してトリミングすることができます。&lt;br /&gt;
====プレビューで透過画像を作成する====&lt;br /&gt;
[[File:instant_alpha.png|300px]]&lt;br /&gt;
&lt;br /&gt;
* command + x&lt;br /&gt;
*　範囲を切り取り、貼り付け&lt;br /&gt;
&lt;br /&gt;
===TIps===&lt;br /&gt;
----&lt;br /&gt;
====スリープ====&lt;br /&gt;
----&lt;br /&gt;
*option + command + メディア取り出し&lt;br /&gt;
&lt;br /&gt;
====古いOS用のアプリを入手する====&lt;br /&gt;
----&lt;br /&gt;
*https://filehippo.jp/&lt;br /&gt;
&lt;br /&gt;
=====[https://filehippo.jp/mac/download_microsoft_remote_desktop/ Microsoft Remote Desktop]=====&lt;br /&gt;
=====[https://amzn.to/3vl3F1R Kindle for mac]=====&lt;br /&gt;
&lt;br /&gt;
=====[https://developer.apple.com/download/more/ XCode]=====&lt;br /&gt;
&lt;br /&gt;
====treeコマンドのインストール====&lt;br /&gt;
&lt;br /&gt;
 brew install tree&lt;br /&gt;
&lt;br /&gt;
===トラブルシュート===&lt;br /&gt;
----&lt;br /&gt;
====Xcodeがインストール中で終わらない====&lt;br /&gt;
----&lt;br /&gt;
*いったんアンインストールしてから、AppStoreからインストール&lt;br /&gt;
&lt;br /&gt;
===ツールインストール===&lt;br /&gt;
*[[Java SE]]&lt;br /&gt;
*[[Node.js]]&lt;br /&gt;
*[[Dart]]&lt;br /&gt;
*[[Flutter]]&lt;/div&gt;</summary>
		<author><name>Piroto</name></author>
		
	</entry>
	<entry>
		<id>https://www.typea.info/tips_/index.php?title=Mac&amp;diff=35369</id>
		<title>Mac</title>
		<link rel="alternate" type="text/html" href="https://www.typea.info/tips_/index.php?title=Mac&amp;diff=35369"/>
		<updated>2024-12-31T00:49:03Z</updated>

		<summary type="html">&lt;p&gt;Piroto: /* Appleシリコンを搭載したMacをセーフモードで起動する */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;| [[Xcode]] | [[Swift]] | [[SwiftUI]] | [[Ubuntu]] | [[Docker]] |&lt;br /&gt;
==[[Mac]]==&lt;br /&gt;
&lt;br /&gt;
{{amazon|4800712785}}&lt;br /&gt;
&lt;br /&gt;
*[[Mac 使い方メモ]]&lt;br /&gt;
&lt;br /&gt;
===基本===&lt;br /&gt;
----&lt;br /&gt;
====hostnameを変更====&lt;br /&gt;
# メニュー - 「システム環境設定」 - 「共有」&lt;br /&gt;
# 「編集」をクリックし、新しいローカルホスト名を入力&lt;br /&gt;
&lt;br /&gt;
====シェルをbashに変更====&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
% cat /etc/shells&lt;br /&gt;
/bin/bash&lt;br /&gt;
/bin/csh&lt;br /&gt;
    :&lt;br /&gt;
% chsh -s /bin/bash&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===キーバインド===&lt;br /&gt;
----&lt;br /&gt;
====バックスラッシュの入力====&lt;br /&gt;
----&lt;br /&gt;
*option + ¥&lt;br /&gt;
&lt;br /&gt;
====日本語入力====&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
*Windows風キー入力&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| キー&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| 意味&lt;br /&gt;
|-&lt;br /&gt;
| ctrl + u&lt;br /&gt;
| ひらがな&lt;br /&gt;
|-&lt;br /&gt;
| ctrl + i&lt;br /&gt;
| カタカナ&lt;br /&gt;
|-&lt;br /&gt;
| ctrl + o&lt;br /&gt;
| 半角英数&lt;br /&gt;
|-&lt;br /&gt;
| ctrl + p&lt;br /&gt;
| 全角英数&lt;br /&gt;
|-&lt;br /&gt;
| ctrl + k&lt;br /&gt;
| 選択中の文節を縮める&lt;br /&gt;
|-&lt;br /&gt;
| ctrｌ + l&lt;br /&gt;
| 選択中の文節を伸ばす&lt;br /&gt;
|-&lt;br /&gt;
| 範囲選択し、かな×2回&lt;br /&gt;
| 再変換&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
=====日本語入力中に数字を半角入力する=====&lt;br /&gt;
*環境設定 ー キーボード ー 日本語ローマ字入力 ー 入力ソース ー 「数字を全角入力」のチェックをOFF&lt;br /&gt;
&lt;br /&gt;
====ツール====&lt;br /&gt;
=====画面キャプチャ=====&lt;br /&gt;
ctrl 長押し＋以下を行うと、クリップボードにコピーされる&lt;br /&gt;
&lt;br /&gt;
*[shift]キー＋[command]キー＋[3]キーで画面全体を撮る&lt;br /&gt;
*[shift]キー＋[command]キー＋[4]キーで画面の一部を撮る&lt;br /&gt;
*[shift]キー＋[command]キー＋[4]キー→ [Space]キーでウィンドウ&lt;br /&gt;
*[shift]キー＋[command]キー＋[5]キー→オプション&lt;br /&gt;
&lt;br /&gt;
=====動画キャプチャ=====&lt;br /&gt;
*音声を取得するには[https://github.com/mattingalls/Soundflower/releases Soundflower]をインストールし、shift + command + 5 のオプションから入力を指定&lt;br /&gt;
&lt;br /&gt;
====キーボード記号====&lt;br /&gt;
----&lt;br /&gt;
*https://support.apple.com/ja-jp/guide/mac-help/cpmh0011/mac&lt;br /&gt;
[[File:Mac_keyboard_sign1.png|400px]]&lt;br /&gt;
[[File:Mac_keyboard_sign2.png|400px]]&lt;br /&gt;
&lt;br /&gt;
===Finder===&lt;br /&gt;
----&lt;br /&gt;
====ショートカット====&lt;br /&gt;
*http://inforati.jp/apple/mac-tips-techniques/system-hints/how-to-use-mac-finder-with-keyboard-shortcut.html&lt;br /&gt;
=====実行(command+o)=====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=====ファイルのカット＆ペースト=====&lt;br /&gt;
# command+c&lt;br /&gt;
# option+command+v&lt;br /&gt;
&lt;br /&gt;
====サイドバーにホームディレクトリを表示====&lt;br /&gt;
----&lt;br /&gt;
*メニューー環境設定ーサイドバー&lt;br /&gt;
====ターミナルから開く====&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ open .&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====場所を指定して開く====&lt;br /&gt;
----&lt;br /&gt;
*Command + G で場所を入力&lt;br /&gt;
====システムフォルダを開く====&lt;br /&gt;
----&lt;br /&gt;
*一時的&lt;br /&gt;
**Command + G で場所を入力&lt;br /&gt;
*継続的&lt;br /&gt;
**以下のコマンドを入力、リブート&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
defaults write com.apple.Finder AppleShowAllFiles YES&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
[[File:Finder_show_all.png|400px]]&lt;br /&gt;
&lt;br /&gt;
===高速化手法===&lt;br /&gt;
----&lt;br /&gt;
====メモリを解放====&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ sudo purge&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
*https://commte.net/6966&lt;br /&gt;
=====セーフブートモードで起動=====&lt;br /&gt;
----&lt;br /&gt;
セーフブートモードで起動すると、ディレクトリのメンテナンスと膨大な量のシステムキャッシュファイルを削除してくれます。通常はShiftキーを押しながら起動&lt;br /&gt;
&lt;br /&gt;
=====Macmini reset=====&lt;br /&gt;
*システム終了します。&lt;br /&gt;
*電源コードを抜いて、15秒間待ちます。&lt;br /&gt;
*電源コードを差し直して、5秒間待ちます。&lt;br /&gt;
*電源ボタンを押して起動します。&lt;br /&gt;
&lt;br /&gt;
====パフォーマンス改善====&lt;br /&gt;
*https://blog.avast.com/jp/guide-to-speeding-and-cleaning-mac&lt;br /&gt;
=====ディスクスキャン=====&lt;br /&gt;
*スキャンを実行するには、メニュー バーの [移動] をクリックして [ユーティリティ] に移動します。ここで [ディスク ユーティリティ] をクリックします。メイン ハード ディスクを選択して [First Aid] をクリックします。&lt;br /&gt;
====SMC のリセット====&lt;br /&gt;
----&lt;br /&gt;
*着脱不能バッテリーを搭載した MacBook の場合、SMC をリセットするには、Mac を完全にシャットダウンする必要があります。次に、Mac の電源がオフになっている間に、キーボードの左側の [SHIFT] + [CONTROL] + [OPTION] キーを押しながら電源ボタンを押します。これらすべてのキーを 10 秒間押し続けます（指がつらないように気を付けてください）。キーを離し、通常どおりに Mac の電源を入れます。&lt;br /&gt;
&lt;br /&gt;
===ディスク容量を増やす===&lt;br /&gt;
----&lt;br /&gt;
====このMacストレージを管理====&lt;br /&gt;
----&lt;br /&gt;
*https://support.apple.com/ja-jp/HT206996&lt;br /&gt;
*Apple メニュー  &amp;gt;「この Mac について」の順に選択し、「ストレージ」をクリックします。&lt;br /&gt;
*棒グラフの各セグメントは、ファイルのカテゴリごとのストレージ使用量の概算値を表しています。各セグメントの上にポインタを置くと、詳細情報が表示されます。&lt;br /&gt;
*ストレージ管理のウインドウには、ストレージを最適に使うための対策が「おすすめ」として表示されます&lt;br /&gt;
====セーフブートモードで起動====&lt;br /&gt;
----&lt;br /&gt;
[https://support.apple.com/ja-jp/guide/mac-help/mh21245/mac セーフブートモードで起動]すると、ディレクトリのメンテナンスと膨大な量のシステムキャッシュファイルを削除してくれます。通常はShiftキーを押しながら起動&lt;br /&gt;
&lt;br /&gt;
=====Appleシリコンを搭載したMacをセーフモードで起動する=====&lt;br /&gt;
#Macで、アップルメニュー  ＞「システム終了」と選択します。&lt;br /&gt;
#Macが完全にシステム終了するまで待ちます。Macが完全にシステム終了すると画面が黒くなり、すべてのランプ（Touch Barのランプを含む）が消えます。&lt;br /&gt;
#「起動オプションを読み込み中」と表示されるまで、Macの電源ボタンを押したままにします。&lt;br /&gt;
#ボリュームを選択します。&lt;br /&gt;
#Shiftキーを押したまま、「セーフモードで続ける」をクリックします。&lt;br /&gt;
#コンピュータは自動的に再起動します。ログインウインドウが表示されたら、メニューバーに「セーフブート」と表示されます。&lt;br /&gt;
&lt;br /&gt;
=====Intelプロセッサを搭載したMacをセーフモードで起動する=====&lt;br /&gt;
+Macを起動または再起動したらすぐにShiftキーを押したままにして、ログインウインドウが表示されたら放します。&lt;br /&gt;
+Macにログインします。&lt;br /&gt;
+もう一度ログインするように求められる場合があります。&lt;br /&gt;
+最初または2番目のログインウインドウのいずれかで、メニューバーに「セーフブート」と表示されます。&lt;br /&gt;
&lt;br /&gt;
====Homebrew====&lt;br /&gt;
*[https://www.typea.info/tips_/index.php/Node.js#Homebrew_.E3.82.A4.E3.83.B3.E3.82.B9.E3.83.88.E3.83.BC.E3.83.AB Homebrewのインストール]&lt;br /&gt;
*Homebrewのキャッシュ削除&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
$ brew cleanup&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===管理===&lt;br /&gt;
----&lt;br /&gt;
====Remote Desktop====&lt;br /&gt;
----&lt;br /&gt;
=====[http://typea.info/blg/glob/2020/01/macwindows10.html Macからホスト名でWindows10にリモートデスクトップ接続]=====&lt;br /&gt;
----&lt;br /&gt;
*[http://typea.info/blg/glob/2020/01/macwindows10.html Macからホスト名でWindows10にリモートデスクトップ接続]&lt;br /&gt;
&lt;br /&gt;
=====IME切り替え=====&lt;br /&gt;
----&lt;br /&gt;
*[[Windows]]にリモート接続し、IMEを切り替えるショートカットをIMEの設定から有効にする&lt;br /&gt;
[[File:mac_remote_win_ime.png|400px]]&lt;br /&gt;
=====バックスラッシュ入力できない問題=====&lt;br /&gt;
* https://qiita.com/KNaito/items/e4436cb73f9ff257394d&lt;br /&gt;
* https://blog.tsukumijima.net/article/mac-windows-keyboard-tweek/&lt;br /&gt;
* https://karabiner-elements.pqrs.org/&lt;br /&gt;
* https://karabiner-elements.pqrs.org/docs/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
bundle_identifiers&lt;br /&gt;
* https://karabiner-elements.pqrs.org/docs/json/complex-modifications-manipulator-definition/conditions/frontmost-application/&lt;br /&gt;
*[https://www.typea.info/blog/index.php/2022/02/03/input_backslash_to_win_via_mac_remote_desktop/ MacリモートデスクトップからWindows¥入力]&lt;br /&gt;
&lt;br /&gt;
====SSHポートフォワーディング====&lt;br /&gt;
----&lt;br /&gt;
*ssh -L {localhostからアクセスするポート}:{踏み台経由でアクセスしたいサーバーアドレス} {踏み台となるサーバー}&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ ssh -L 10443:192.168.64.2:10443 hirotoyagi@delhi.local&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
*上記でSSH接続した状態で、localhost:ポート に接続する&lt;br /&gt;
&lt;br /&gt;
===画像===&lt;br /&gt;
----&lt;br /&gt;
====プレビューでトリミング====&lt;br /&gt;
----&lt;br /&gt;
トリミングを行いたい画像をダブルクリックすると、基本的にはプレビューが自動的に起動します。 この画像の上でクリックをしたまま、引っ張ると四角く範囲を選択することができます。 トリミングしたい部分で、クリックを離します。 選択範囲に問題がなければ、command+Kを押してトリミングすることができます。&lt;br /&gt;
====プレビューで透過画像を作成する====&lt;br /&gt;
[[File:instant_alpha.png|300px]]&lt;br /&gt;
&lt;br /&gt;
* command + x&lt;br /&gt;
*　範囲を切り取り、貼り付け&lt;br /&gt;
&lt;br /&gt;
===TIps===&lt;br /&gt;
----&lt;br /&gt;
====スリープ====&lt;br /&gt;
----&lt;br /&gt;
*option + command + メディア取り出し&lt;br /&gt;
&lt;br /&gt;
====古いOS用のアプリを入手する====&lt;br /&gt;
----&lt;br /&gt;
*https://filehippo.jp/&lt;br /&gt;
&lt;br /&gt;
=====[https://filehippo.jp/mac/download_microsoft_remote_desktop/ Microsoft Remote Desktop]=====&lt;br /&gt;
=====[https://amzn.to/3vl3F1R Kindle for mac]=====&lt;br /&gt;
&lt;br /&gt;
=====[https://developer.apple.com/download/more/ XCode]=====&lt;br /&gt;
&lt;br /&gt;
====treeコマンドのインストール====&lt;br /&gt;
&lt;br /&gt;
 brew install tree&lt;br /&gt;
&lt;br /&gt;
===トラブルシュート===&lt;br /&gt;
----&lt;br /&gt;
====Xcodeがインストール中で終わらない====&lt;br /&gt;
----&lt;br /&gt;
*いったんアンインストールしてから、AppStoreからインストール&lt;br /&gt;
&lt;br /&gt;
===ツールインストール===&lt;br /&gt;
*[[Java SE]]&lt;br /&gt;
*[[Node.js]]&lt;br /&gt;
*[[Dart]]&lt;br /&gt;
*[[Flutter]]&lt;/div&gt;</summary>
		<author><name>Piroto</name></author>
		
	</entry>
	<entry>
		<id>https://www.typea.info/tips_/index.php?title=Mac&amp;diff=35368</id>
		<title>Mac</title>
		<link rel="alternate" type="text/html" href="https://www.typea.info/tips_/index.php?title=Mac&amp;diff=35368"/>
		<updated>2024-12-31T00:48:21Z</updated>

		<summary type="html">&lt;p&gt;Piroto: /* セーフブートモードで起動 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;| [[Xcode]] | [[Swift]] | [[SwiftUI]] | [[Ubuntu]] | [[Docker]] |&lt;br /&gt;
==[[Mac]]==&lt;br /&gt;
&lt;br /&gt;
{{amazon|4800712785}}&lt;br /&gt;
&lt;br /&gt;
*[[Mac 使い方メモ]]&lt;br /&gt;
&lt;br /&gt;
===基本===&lt;br /&gt;
----&lt;br /&gt;
====hostnameを変更====&lt;br /&gt;
# メニュー - 「システム環境設定」 - 「共有」&lt;br /&gt;
# 「編集」をクリックし、新しいローカルホスト名を入力&lt;br /&gt;
&lt;br /&gt;
====シェルをbashに変更====&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
% cat /etc/shells&lt;br /&gt;
/bin/bash&lt;br /&gt;
/bin/csh&lt;br /&gt;
    :&lt;br /&gt;
% chsh -s /bin/bash&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===キーバインド===&lt;br /&gt;
----&lt;br /&gt;
====バックスラッシュの入力====&lt;br /&gt;
----&lt;br /&gt;
*option + ¥&lt;br /&gt;
&lt;br /&gt;
====日本語入力====&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
*Windows風キー入力&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| キー&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| 意味&lt;br /&gt;
|-&lt;br /&gt;
| ctrl + u&lt;br /&gt;
| ひらがな&lt;br /&gt;
|-&lt;br /&gt;
| ctrl + i&lt;br /&gt;
| カタカナ&lt;br /&gt;
|-&lt;br /&gt;
| ctrl + o&lt;br /&gt;
| 半角英数&lt;br /&gt;
|-&lt;br /&gt;
| ctrl + p&lt;br /&gt;
| 全角英数&lt;br /&gt;
|-&lt;br /&gt;
| ctrl + k&lt;br /&gt;
| 選択中の文節を縮める&lt;br /&gt;
|-&lt;br /&gt;
| ctrｌ + l&lt;br /&gt;
| 選択中の文節を伸ばす&lt;br /&gt;
|-&lt;br /&gt;
| 範囲選択し、かな×2回&lt;br /&gt;
| 再変換&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
=====日本語入力中に数字を半角入力する=====&lt;br /&gt;
*環境設定 ー キーボード ー 日本語ローマ字入力 ー 入力ソース ー 「数字を全角入力」のチェックをOFF&lt;br /&gt;
&lt;br /&gt;
====ツール====&lt;br /&gt;
=====画面キャプチャ=====&lt;br /&gt;
ctrl 長押し＋以下を行うと、クリップボードにコピーされる&lt;br /&gt;
&lt;br /&gt;
*[shift]キー＋[command]キー＋[3]キーで画面全体を撮る&lt;br /&gt;
*[shift]キー＋[command]キー＋[4]キーで画面の一部を撮る&lt;br /&gt;
*[shift]キー＋[command]キー＋[4]キー→ [Space]キーでウィンドウ&lt;br /&gt;
*[shift]キー＋[command]キー＋[5]キー→オプション&lt;br /&gt;
&lt;br /&gt;
=====動画キャプチャ=====&lt;br /&gt;
*音声を取得するには[https://github.com/mattingalls/Soundflower/releases Soundflower]をインストールし、shift + command + 5 のオプションから入力を指定&lt;br /&gt;
&lt;br /&gt;
====キーボード記号====&lt;br /&gt;
----&lt;br /&gt;
*https://support.apple.com/ja-jp/guide/mac-help/cpmh0011/mac&lt;br /&gt;
[[File:Mac_keyboard_sign1.png|400px]]&lt;br /&gt;
[[File:Mac_keyboard_sign2.png|400px]]&lt;br /&gt;
&lt;br /&gt;
===Finder===&lt;br /&gt;
----&lt;br /&gt;
====ショートカット====&lt;br /&gt;
*http://inforati.jp/apple/mac-tips-techniques/system-hints/how-to-use-mac-finder-with-keyboard-shortcut.html&lt;br /&gt;
=====実行(command+o)=====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=====ファイルのカット＆ペースト=====&lt;br /&gt;
# command+c&lt;br /&gt;
# option+command+v&lt;br /&gt;
&lt;br /&gt;
====サイドバーにホームディレクトリを表示====&lt;br /&gt;
----&lt;br /&gt;
*メニューー環境設定ーサイドバー&lt;br /&gt;
====ターミナルから開く====&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ open .&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====場所を指定して開く====&lt;br /&gt;
----&lt;br /&gt;
*Command + G で場所を入力&lt;br /&gt;
====システムフォルダを開く====&lt;br /&gt;
----&lt;br /&gt;
*一時的&lt;br /&gt;
**Command + G で場所を入力&lt;br /&gt;
*継続的&lt;br /&gt;
**以下のコマンドを入力、リブート&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
defaults write com.apple.Finder AppleShowAllFiles YES&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
[[File:Finder_show_all.png|400px]]&lt;br /&gt;
&lt;br /&gt;
===高速化手法===&lt;br /&gt;
----&lt;br /&gt;
====メモリを解放====&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ sudo purge&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
*https://commte.net/6966&lt;br /&gt;
=====セーフブートモードで起動=====&lt;br /&gt;
----&lt;br /&gt;
セーフブートモードで起動すると、ディレクトリのメンテナンスと膨大な量のシステムキャッシュファイルを削除してくれます。通常はShiftキーを押しながら起動&lt;br /&gt;
&lt;br /&gt;
=====Macmini reset=====&lt;br /&gt;
*システム終了します。&lt;br /&gt;
*電源コードを抜いて、15秒間待ちます。&lt;br /&gt;
*電源コードを差し直して、5秒間待ちます。&lt;br /&gt;
*電源ボタンを押して起動します。&lt;br /&gt;
&lt;br /&gt;
====パフォーマンス改善====&lt;br /&gt;
*https://blog.avast.com/jp/guide-to-speeding-and-cleaning-mac&lt;br /&gt;
=====ディスクスキャン=====&lt;br /&gt;
*スキャンを実行するには、メニュー バーの [移動] をクリックして [ユーティリティ] に移動します。ここで [ディスク ユーティリティ] をクリックします。メイン ハード ディスクを選択して [First Aid] をクリックします。&lt;br /&gt;
====SMC のリセット====&lt;br /&gt;
----&lt;br /&gt;
*着脱不能バッテリーを搭載した MacBook の場合、SMC をリセットするには、Mac を完全にシャットダウンする必要があります。次に、Mac の電源がオフになっている間に、キーボードの左側の [SHIFT] + [CONTROL] + [OPTION] キーを押しながら電源ボタンを押します。これらすべてのキーを 10 秒間押し続けます（指がつらないように気を付けてください）。キーを離し、通常どおりに Mac の電源を入れます。&lt;br /&gt;
&lt;br /&gt;
===ディスク容量を増やす===&lt;br /&gt;
----&lt;br /&gt;
====このMacストレージを管理====&lt;br /&gt;
----&lt;br /&gt;
*https://support.apple.com/ja-jp/HT206996&lt;br /&gt;
*Apple メニュー  &amp;gt;「この Mac について」の順に選択し、「ストレージ」をクリックします。&lt;br /&gt;
*棒グラフの各セグメントは、ファイルのカテゴリごとのストレージ使用量の概算値を表しています。各セグメントの上にポインタを置くと、詳細情報が表示されます。&lt;br /&gt;
*ストレージ管理のウインドウには、ストレージを最適に使うための対策が「おすすめ」として表示されます&lt;br /&gt;
====セーフブートモードで起動====&lt;br /&gt;
----&lt;br /&gt;
[https://support.apple.com/ja-jp/guide/mac-help/mh21245/mac セーフブートモードで起動]すると、ディレクトリのメンテナンスと膨大な量のシステムキャッシュファイルを削除してくれます。通常はShiftキーを押しながら起動&lt;br /&gt;
&lt;br /&gt;
=====Appleシリコンを搭載したMacをセーフモードで起動する=====&lt;br /&gt;
+Macで、アップルメニュー  ＞「システム終了」と選択します。&lt;br /&gt;
+Macが完全にシステム終了するまで待ちます。Macが完全にシステム終了すると画面が黒くなり、すべてのランプ（Touch Barのランプを含む）が消えます。&lt;br /&gt;
+「起動オプションを読み込み中」と表示されるまで、Macの電源ボタンを押したままにします。&lt;br /&gt;
+ボリュームを選択します。&lt;br /&gt;
+Shiftキーを押したまま、「セーフモードで続ける」をクリックします。&lt;br /&gt;
+コンピュータは自動的に再起動します。ログインウインドウが表示されたら、メニューバーに「セーフブート」と表示されます。&lt;br /&gt;
=====Intelプロセッサを搭載したMacをセーフモードで起動する=====&lt;br /&gt;
+Macを起動または再起動したらすぐにShiftキーを押したままにして、ログインウインドウが表示されたら放します。&lt;br /&gt;
+Macにログインします。&lt;br /&gt;
+もう一度ログインするように求められる場合があります。&lt;br /&gt;
+最初または2番目のログインウインドウのいずれかで、メニューバーに「セーフブート」と表示されます。&lt;br /&gt;
&lt;br /&gt;
====Homebrew====&lt;br /&gt;
*[https://www.typea.info/tips_/index.php/Node.js#Homebrew_.E3.82.A4.E3.83.B3.E3.82.B9.E3.83.88.E3.83.BC.E3.83.AB Homebrewのインストール]&lt;br /&gt;
*Homebrewのキャッシュ削除&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
$ brew cleanup&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===管理===&lt;br /&gt;
----&lt;br /&gt;
====Remote Desktop====&lt;br /&gt;
----&lt;br /&gt;
=====[http://typea.info/blg/glob/2020/01/macwindows10.html Macからホスト名でWindows10にリモートデスクトップ接続]=====&lt;br /&gt;
----&lt;br /&gt;
*[http://typea.info/blg/glob/2020/01/macwindows10.html Macからホスト名でWindows10にリモートデスクトップ接続]&lt;br /&gt;
&lt;br /&gt;
=====IME切り替え=====&lt;br /&gt;
----&lt;br /&gt;
*[[Windows]]にリモート接続し、IMEを切り替えるショートカットをIMEの設定から有効にする&lt;br /&gt;
[[File:mac_remote_win_ime.png|400px]]&lt;br /&gt;
=====バックスラッシュ入力できない問題=====&lt;br /&gt;
* https://qiita.com/KNaito/items/e4436cb73f9ff257394d&lt;br /&gt;
* https://blog.tsukumijima.net/article/mac-windows-keyboard-tweek/&lt;br /&gt;
* https://karabiner-elements.pqrs.org/&lt;br /&gt;
* https://karabiner-elements.pqrs.org/docs/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
bundle_identifiers&lt;br /&gt;
* https://karabiner-elements.pqrs.org/docs/json/complex-modifications-manipulator-definition/conditions/frontmost-application/&lt;br /&gt;
*[https://www.typea.info/blog/index.php/2022/02/03/input_backslash_to_win_via_mac_remote_desktop/ MacリモートデスクトップからWindows¥入力]&lt;br /&gt;
&lt;br /&gt;
====SSHポートフォワーディング====&lt;br /&gt;
----&lt;br /&gt;
*ssh -L {localhostからアクセスするポート}:{踏み台経由でアクセスしたいサーバーアドレス} {踏み台となるサーバー}&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ ssh -L 10443:192.168.64.2:10443 hirotoyagi@delhi.local&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
*上記でSSH接続した状態で、localhost:ポート に接続する&lt;br /&gt;
&lt;br /&gt;
===画像===&lt;br /&gt;
----&lt;br /&gt;
====プレビューでトリミング====&lt;br /&gt;
----&lt;br /&gt;
トリミングを行いたい画像をダブルクリックすると、基本的にはプレビューが自動的に起動します。 この画像の上でクリックをしたまま、引っ張ると四角く範囲を選択することができます。 トリミングしたい部分で、クリックを離します。 選択範囲に問題がなければ、command+Kを押してトリミングすることができます。&lt;br /&gt;
====プレビューで透過画像を作成する====&lt;br /&gt;
[[File:instant_alpha.png|300px]]&lt;br /&gt;
&lt;br /&gt;
* command + x&lt;br /&gt;
*　範囲を切り取り、貼り付け&lt;br /&gt;
&lt;br /&gt;
===TIps===&lt;br /&gt;
----&lt;br /&gt;
====スリープ====&lt;br /&gt;
----&lt;br /&gt;
*option + command + メディア取り出し&lt;br /&gt;
&lt;br /&gt;
====古いOS用のアプリを入手する====&lt;br /&gt;
----&lt;br /&gt;
*https://filehippo.jp/&lt;br /&gt;
&lt;br /&gt;
=====[https://filehippo.jp/mac/download_microsoft_remote_desktop/ Microsoft Remote Desktop]=====&lt;br /&gt;
=====[https://amzn.to/3vl3F1R Kindle for mac]=====&lt;br /&gt;
&lt;br /&gt;
=====[https://developer.apple.com/download/more/ XCode]=====&lt;br /&gt;
&lt;br /&gt;
====treeコマンドのインストール====&lt;br /&gt;
&lt;br /&gt;
 brew install tree&lt;br /&gt;
&lt;br /&gt;
===トラブルシュート===&lt;br /&gt;
----&lt;br /&gt;
====Xcodeがインストール中で終わらない====&lt;br /&gt;
----&lt;br /&gt;
*いったんアンインストールしてから、AppStoreからインストール&lt;br /&gt;
&lt;br /&gt;
===ツールインストール===&lt;br /&gt;
*[[Java SE]]&lt;br /&gt;
*[[Node.js]]&lt;br /&gt;
*[[Dart]]&lt;br /&gt;
*[[Flutter]]&lt;/div&gt;</summary>
		<author><name>Piroto</name></author>
		
	</entry>
	<entry>
		<id>https://www.typea.info/tips_/index.php?title=SwiftUI&amp;diff=35367</id>
		<title>SwiftUI</title>
		<link rel="alternate" type="text/html" href="https://www.typea.info/tips_/index.php?title=SwiftUI&amp;diff=35367"/>
		<updated>2024-12-29T07:39:48Z</updated>

		<summary type="html">&lt;p&gt;Piroto: /* Tips */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;| [[Swift]] | [[Mac]] | [[Xcode]] | [[Swift Sample]] | [[Cocoa]] | [[Xamarin.Mac]] |&lt;br /&gt;
&lt;br /&gt;
{{amazon|B082SMJC7V}}&lt;br /&gt;
&lt;br /&gt;
==SwiftUI==&lt;br /&gt;
*[https://developer.apple.com/jp/xcode/swiftui/ SwiftUI]&lt;br /&gt;
*[https://developer.apple.com/documentation/swiftui/ SwiftUI Documents]&lt;br /&gt;
*[https://www.raywenderlich.com/macos macos tutorials]&lt;br /&gt;
*1セットのツールとAPIを使用するだけで、あらゆるAppleデバイス向けのユーザーインターフェイスを構築&lt;br /&gt;
*宣言型シンタックスを使&lt;br /&gt;
*宣言型のスタイルは、アニメーションなどの複雑な概念にも適用&lt;br /&gt;
===デザインツール===&lt;br /&gt;
*Xcodeには、SwiftUIでのインターフェイス構築をドラッグ＆ドロップのように簡単に行える直感的な新しいデザインツールが含まれています&lt;br /&gt;
*デザインキャンバスでの編集内容と、隣接するエディタ内のコードはすべて完全に同期されます&lt;br /&gt;
====ドラッグ＆ドロップ====&lt;br /&gt;
*ユーザーインターフェイス内のコンポーネントの位置は、キャンバス上でコントロールをドラッグするだけで調整できます&lt;br /&gt;
====ダイナミックリプレースメント====&lt;br /&gt;
*wiftのコンパイラとランタイムはXcode全体に完全に埋め込まれているため、Appは常にビルドされ実行されます&lt;br /&gt;
*表示されるデザインキャンバスは、単にユーザーインターフェイスに似せたものではなく、実際のAppそのもの&lt;br /&gt;
*Xcodeは編集したコードを実際のAppに直接組み入れることができます&lt;br /&gt;
====プレビュー====&lt;br /&gt;
*プレビューを1つまたは複数作成して、サンプルデータを取得できる&lt;br /&gt;
&lt;br /&gt;
===Swift UI チュートリアルをやってみる===&lt;br /&gt;
----&lt;br /&gt;
*[https://www.typea.info/blog/index.php/2020/12/09/swiftui_tutorial_youtube_memo/  プロジェクト作成〜TextViewのカスタマイズ]&lt;br /&gt;
*[[Xcode]]&lt;br /&gt;
*resume -&amp;gt; プレビュー&lt;br /&gt;
*command + click -&amp;gt; Action List&lt;br /&gt;
*右上の +　ボタンでコントロール追加&lt;br /&gt;
&lt;br /&gt;
====[[Xcode]] ナビゲーター====&lt;br /&gt;
----&lt;br /&gt;
[[File:xcode_navgator_icons.png|400px]]&lt;br /&gt;
左から&lt;br /&gt;
#プロジェクトナビゲーター&lt;br /&gt;
#ソースコントロールナビゲーター&lt;br /&gt;
#シンボルナビゲーター&lt;br /&gt;
#検索ナビゲーター&lt;br /&gt;
#イシューナビゲーター&lt;br /&gt;
#テストナビゲーター&lt;br /&gt;
#デバッグナビゲーター&lt;br /&gt;
#ブレークポイントナビゲーター&lt;br /&gt;
#レポートナビゲーター&lt;br /&gt;
&lt;br /&gt;
====[https://www.typea.info/blog/index.php/2020/12/09/swiftui_tutorial_youtube_memo/  プロジェクト作成〜TextViewのカスタマイズ]====&lt;br /&gt;
====[https://www.typea.info/blog/index.php/2020/12/19/swiftui_tutorial_custom_image_view/  Custom Image Viewの作成]====&lt;br /&gt;
====[https://www.typea.info/blog/index.php/2020/12/06/xcode_macos_proguramming/  Xcodeを使ってmacOS プログラミングとplaygroundの作成]====&lt;br /&gt;
====[https://www.typea.info/blog/index.php/2021/01/23/swiftui_tutorial_list_navigation/  Listとナビゲーションとプレビュー]====&lt;br /&gt;
&lt;br /&gt;
==レイアウト==&lt;br /&gt;
===[https://d1v1b.com/swiftui/alignment Alignment]===&lt;br /&gt;
----&lt;br /&gt;
*[https://d1v1b.com/swiftui/alignment Alignment]&lt;br /&gt;
&lt;br /&gt;
===[https://t32k.me/mol/log/margin-padding-swiftui/ 余白の取り方]===&lt;br /&gt;
----&lt;br /&gt;
*[https://t32k.me/mol/log/margin-padding-swiftui/ 余白の取り方]&lt;br /&gt;
*記述箇所によって、表示が変わる&lt;br /&gt;
&lt;br /&gt;
*backgroundにpaddingを指定する（cssのmargin的な効果)&lt;br /&gt;
[[File:swiftui_padding2.png|300px]]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  Text(host.host)&lt;br /&gt;
       .background(Color.green)&lt;br /&gt;
       .padding()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
*Textにpaddingを指定することになる(cssのpadding的効果)&lt;br /&gt;
[[File:swiftui_padding1.png|300px]]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  Text(host.host)&lt;br /&gt;
       .padding()&lt;br /&gt;
       .background(Color.green)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===ボタンサイズ===&lt;br /&gt;
----&lt;br /&gt;
*ボタンのサイズを内容にフィットさせたい&lt;br /&gt;
[[File:swiftui_button_size1.png|300px]]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  Button(action: {}) {&lt;br /&gt;
     VStack{&lt;br /&gt;
         :&lt;br /&gt;
     }&lt;br /&gt;
    .padding()&lt;br /&gt;
    .border(Color.blue, width: 3)&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
*.buttonStyle(PlainButtonStyle()) を指定&lt;br /&gt;
[[File:swiftui_button_size2.png|300px]]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Button(action: {}) {&lt;br /&gt;
   VStack{&lt;br /&gt;
         :&lt;br /&gt;
     }&lt;br /&gt;
    .padding()&lt;br /&gt;
    .border(Color.blue, width: 3)&lt;br /&gt;
}.buttonStyle(PlainButtonStyle())&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
===親Viewのサイズ情報を取得する===&lt;br /&gt;
----&lt;br /&gt;
*https://qiita.com/masa7351/items/0567969f93cc88d714ac&lt;br /&gt;
*https://www.hackingwithswift.com/quick-start/swiftui/how-to-make-two-views-the-same-width-or-height&lt;br /&gt;
[[File:swiftui_grid_layout1.png|200px]]&lt;br /&gt;
[[File:swiftui_grid_layout2.png|400px]]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
struct HostView : View {&lt;br /&gt;
    var host: WoL.Host&lt;br /&gt;
    var body: some View {&lt;br /&gt;
        GeometryReader { geo in&lt;br /&gt;
            HStack() {&lt;br /&gt;
                Text(host.host)&lt;br /&gt;
                    .padding()&lt;br /&gt;
                    .frame(width:  geo.size.width * 0.33 , alignment: .leading)&lt;br /&gt;
                    .frame(maxHeight: .infinity)&lt;br /&gt;
                    .background(Color.red)&lt;br /&gt;
                Text(host.ip)&lt;br /&gt;
                    .padding()&lt;br /&gt;
                    .frame(width: geo.size.width * 0.33 , alignment: .leading)&lt;br /&gt;
                    .frame(maxHeight: .infinity)&lt;br /&gt;
                    .background(Color.green)&lt;br /&gt;
                Text(host.macaddr)&lt;br /&gt;
                    .padding()&lt;br /&gt;
                    .frame(width: geo.size.width * 0.33 , alignment: .leading)&lt;br /&gt;
                    .frame(maxHeight: .infinity)&lt;br /&gt;
                    .background(Color.yellow)&lt;br /&gt;
            }.fixedSize(horizontal: false, vertical: true)&lt;br /&gt;
            &lt;br /&gt;
        }.frame(height: 60)&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===影をつける===&lt;br /&gt;
---&lt;br /&gt;
*shadowを設定すると、内部のコンポーネント全てに影がつく、compositingGroup を指定することで、背景だけに影をつけることができる&lt;br /&gt;
&amp;lt;pre&amp;gt;   &lt;br /&gt;
             :&lt;br /&gt;
        .background()&lt;br /&gt;
        .compositingGroup()&lt;br /&gt;
        .shadow(radius: 10)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
===Card View===&lt;br /&gt;
----&lt;br /&gt;
*[https://www.hackingwithswift.com/books/ios-swiftui/designing-a-single-card-view Card View]&lt;br /&gt;
*LazyGrid &lt;br /&gt;
[[File:swiftui_card_layout1.png|400px]]&lt;br /&gt;
[[File:swiftui_card_layout2.png|200px]]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
            let columns =&lt;br /&gt;
                [GridItem(.adaptive(minimum: 250, maximum: 800))]&lt;br /&gt;
            ScrollView {&lt;br /&gt;
                LazyVGrid(columns: columns, spacing:10) {&lt;br /&gt;
                    ForEach(hosts.hosts, id: \.macaddr) { host in&lt;br /&gt;
                        HostView(host:host)&lt;br /&gt;
                    }&lt;br /&gt;
                } .padding(20)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Toolbar===&lt;br /&gt;
----&lt;br /&gt;
[[File:swiftui_toolbar.png|300lx]]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ScrollView {&lt;br /&gt;
	LazyVGrid(columns: columns) {&lt;br /&gt;
		ForEach(hosts.hosts, id: \.ip) { host in&lt;br /&gt;
			HostView(host:host)&lt;br /&gt;
		}&lt;br /&gt;
	} .padding(20)&lt;br /&gt;
}.toolbar {&lt;br /&gt;
	ToolbarItem(placement: .automatic) {&lt;br /&gt;
		Button(&amp;quot;arp -a&amp;quot;) {&lt;br /&gt;
			WoLService().arp(hosts:self.hosts)&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	ToolbarItem(placement: .automatic) {&lt;br /&gt;
		Button(&amp;quot;load&amp;quot;) {&lt;br /&gt;
			WoLService().load(hosts:self.hosts)&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==データ==&lt;br /&gt;
=== データ変更に応じて画面に反映させる ===&lt;br /&gt;
* 画面の構造体の中でデータを保持しているクラスのインスタンスを格納するプロパティに、@ObservedObjectプロパティラッパーを付与する&lt;br /&gt;
*　データを保持しているクラスを、@ObservableObjectプロトコルに準拠させる&lt;br /&gt;
* クラスの中で変更を反映させる値を保持しているプロパティに、@Publishedプロパティラッパーを付与する&lt;br /&gt;
&lt;br /&gt;
=== UserDefaults===&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===ドキュメントパス===&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)&lt;br /&gt;
print(&amp;quot;Document path: \(paths)&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
*出力&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Document path: [file:///Users/hirotoyagi/Library/Containers/info.typea.WoL/Data/Documents/]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
====ファイル格納先====&lt;br /&gt;
----&lt;br /&gt;
*[https://qiita.com/am10/items/3b2eb3d9f6c6955455b6 ファイル格納先]&lt;br /&gt;
===View間データ受け渡し===&lt;br /&gt;
----&lt;br /&gt;
SwiftUIでは親ビューと子ビュー間で値を渡す方法は、下記の3つが挙げられます。&lt;br /&gt;
&lt;br /&gt;
#Environment&lt;br /&gt;
##Viewが持つ環境変数。独自の環境変数を定義することができ、それを利用して親ビューから任意の値を渡すことが可能&lt;br /&gt;
#EnvironmentObjects&lt;br /&gt;
##他の２つに比べて一般的な方法。利用するためには独自のクラスを定義&lt;br /&gt;
#Preferences&lt;br /&gt;
##Preferenceは子から親へ伝達させる方法&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*https://qiita.com/noby111/items/26405bd89075c841029a&lt;br /&gt;
====ObservableObject を経由して親子ViewでAlertの表示フラグを共有====&lt;br /&gt;
[[File:swiftui_share_object.png|300px]]&lt;br /&gt;
*ObservableObjectを共有して、変更をSubscribeする&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
struct HostListView: View {&lt;br /&gt;
    @ObservedObject var hosts = HostList()&lt;br /&gt;
    @ObservedObject var param = Param()&lt;br /&gt;
    var body: some View {&lt;br /&gt;
        VStack {&lt;br /&gt;
            let columns =&lt;br /&gt;
                [GridItem(.adaptive(minimum: 250, maximum: 800))]&lt;br /&gt;
            ScrollView {&lt;br /&gt;
                LazyVGrid(columns: columns, spacing:10) {&lt;br /&gt;
                    ForEach(hosts.hosts, id: \.id) { host in&lt;br /&gt;
                        HostView(host:host).environmentObject(param)&lt;br /&gt;
                    }&lt;br /&gt;
                } .padding(20)&lt;br /&gt;
            }.alert(isPresented: $param.isSaveAlert, content: {&lt;br /&gt;
                Alert(title: Text(&amp;quot;Title&amp;quot;),message: Text(&amp;quot;Messge&amp;quot;),&lt;br /&gt;
                    primaryButton: .default(Text(&amp;quot;OK&amp;quot;), action: {}),&lt;br /&gt;
                    secondaryButton: .cancel(Text(&amp;quot;Cancel&amp;quot;),action: {}))&lt;br /&gt;
            })&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
struct HostView : View {&lt;br /&gt;
    @ObservedObject var host: WoL.Host&lt;br /&gt;
    @EnvironmentObject var param: Param&lt;br /&gt;
    &lt;br /&gt;
    var body: some View {&lt;br /&gt;
        VStack{&lt;br /&gt;
            HStack {&lt;br /&gt;
                Button(action: {&lt;br /&gt;
                    self.param.isSaveAlert = true&lt;br /&gt;
                }) {&lt;br /&gt;
                    Image(systemName: &amp;quot;square.and.arrow.down&amp;quot;)&lt;br /&gt;
                }.help(Text(&amp;quot;save&amp;quot;))&lt;br /&gt;
            }&lt;br /&gt;
               :            &lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
class Param : ObservableObject {&lt;br /&gt;
    @Published var isSaveAlert: Bool = false&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====@Binding を経由して親子ViewでAlertの表示フラグを共有====&lt;br /&gt;
[[File:swiftui_share_object.png|300px]]&lt;br /&gt;
*@Binding でView間で変数を共有&lt;br /&gt;
*呼び出し側は＠State&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
struct HostListView: View {&lt;br /&gt;
    @ObservedObject var hosts = HostList()&lt;br /&gt;
    @State var isSaveAlert = false&lt;br /&gt;
&lt;br /&gt;
    var body: some View {&lt;br /&gt;
        VStack {&lt;br /&gt;
            let columns =&lt;br /&gt;
                [GridItem(.adaptive(minimum: 250, maximum: 800))]&lt;br /&gt;
            ScrollView {&lt;br /&gt;
                LazyVGrid(columns: columns, spacing:10) {&lt;br /&gt;
                    ForEach(hosts.hosts, id: \.id) { host in&lt;br /&gt;
                        HostView(host:host, isSaveAlert: $isSaveAlert, alertMessage: $alertMessage)&lt;br /&gt;
                    }&lt;br /&gt;
                } .padding(20)&lt;br /&gt;
            }.alert(isPresented: $isSaveAlert, content: {&lt;br /&gt;
                Alert(title: Text(&amp;quot;Title&amp;quot;),message: Text(alertMessage),&lt;br /&gt;
                      primaryButton: .default(Text(&amp;quot;OK&amp;quot;), action: {}),&lt;br /&gt;
                      secondaryButton: .cancel(Text(&amp;quot;Cancel&amp;quot;),action: {}))&lt;br /&gt;
            })&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
struct HostView : View {&lt;br /&gt;
    @ObservedObject var host: WoL.Host&lt;br /&gt;
    @Binding var isSaveAlert: Bool&lt;br /&gt;
    &lt;br /&gt;
    var body: some View {&lt;br /&gt;
        VStack{&lt;br /&gt;
            HStack {&lt;br /&gt;
                Button(action: {&lt;br /&gt;
                    self.isSaveAlert = true&lt;br /&gt;
                }) {&lt;br /&gt;
                    Image(systemName: &amp;quot;square.and.arrow.down&amp;quot;)&lt;br /&gt;
                }.help(Text(&amp;quot;save&amp;quot;))&lt;br /&gt;
                 :&lt;br /&gt;
			}&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
=====@Binding使用時のPreview=====&lt;br /&gt;
*＠Stateかつ、staticで宣言&lt;br /&gt;
*$で変数を渡す&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
struct HostView_Previews: PreviewProvider {&lt;br /&gt;
    @State static var isAlert = true&lt;br /&gt;
&lt;br /&gt;
    static var previews: some View {&lt;br /&gt;
        let host = WoL.Host(host: &amp;quot;test.local&amp;quot;, ip: &amp;quot;192.168.0.1&amp;quot;, macaddr: &amp;quot;aa:bb:cc:dd:ee:ff&amp;quot;, comment: &amp;quot;&amp;quot;)&lt;br /&gt;
        HostView(host: host, isAlert: $isAlert)&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==メニュー==&lt;br /&gt;
===メインメニューに別のViewを開くメニューを追加===&lt;br /&gt;
----&lt;br /&gt;
[[File:swift_ui_main_menu.png|400px]]&lt;br /&gt;
*.commandsを記述&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
@main&lt;br /&gt;
struct WoLApp: App {&lt;br /&gt;
    var body: some Scene {&lt;br /&gt;
        WindowGroup {&lt;br /&gt;
            ContentView()&lt;br /&gt;
        }.commands {&lt;br /&gt;
            CommandGroup(after: CommandGroupPlacement.appInfo) {&lt;br /&gt;
                Divider()&lt;br /&gt;
                NavigationLink(destination: PreferenceView()) {&lt;br /&gt;
                    Text(&amp;quot;preferences&amp;quot;)&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==図形==&lt;br /&gt;
===Capsule===&lt;br /&gt;
----&lt;br /&gt;
[[File:swiftui_capsule.png|200px]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
VStack{&lt;br /&gt;
   :&lt;br /&gt;
}&lt;br /&gt;
.padding()&lt;br /&gt;
.background(&lt;br /&gt;
	Capsule(style: .continuous)&lt;br /&gt;
		.foregroundColor(Color.white)&lt;br /&gt;
)&lt;br /&gt;
.shadow(radius:10 )&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===RoundedRectangle===&lt;br /&gt;
----&lt;br /&gt;
[[File:swiftui_roundedRectangle.png|200px]]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
VStack{&lt;br /&gt;
  :&lt;br /&gt;
}&lt;br /&gt;
.padding()&lt;br /&gt;
.background(&lt;br /&gt;
	RoundedRectangle(cornerRadius: 20)&lt;br /&gt;
		.foregroundColor(Color.white)&lt;br /&gt;
)&lt;br /&gt;
.shadow(radius:10 )&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==画像==&lt;br /&gt;
===SF Symbol アイコン===&lt;br /&gt;
----&lt;br /&gt;
*https://developer.apple.com/design/human-interface-guidelines/sf-symbols/overview/&lt;br /&gt;
*[https://developer.apple.com/sf-symbols/ SF Symbols アプリ]&lt;br /&gt;
&lt;br /&gt;
==コードサンプル(コンポーネント)==&lt;br /&gt;
===Button===&lt;br /&gt;
----&lt;br /&gt;
[[File:swift_sample_button.png|200px]]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import Foundation&lt;br /&gt;
import SwiftUI&lt;br /&gt;
&lt;br /&gt;
struct ButtonView: View {&lt;br /&gt;
&lt;br /&gt;
    @State var cnt:Int = 0;&lt;br /&gt;
    var body: some View {&lt;br /&gt;
        VStack {&lt;br /&gt;
            Button(action: {&lt;br /&gt;
                self.cnt += 1;&lt;br /&gt;
                print(&amp;quot;print \(self.cnt)&amp;quot;)&lt;br /&gt;
            })&lt;br /&gt;
            {&lt;br /&gt;
                Text(&amp;quot;Button+1 (\(self.cnt))&amp;quot;)&lt;br /&gt;
            }&lt;br /&gt;
            .padding(.horizontal, 25.0)&lt;br /&gt;
            .font(.largeTitle)&lt;br /&gt;
            .foregroundColor(Color.white)&lt;br /&gt;
            .background(Color.green)&lt;br /&gt;
            .cornerRadius(15, antialiased: true)&lt;br /&gt;
            Divider()&lt;br /&gt;
            Button(&amp;quot;Button+2 (\(self.cnt))&amp;quot;) {&lt;br /&gt;
                self.cnt += 2;&lt;br /&gt;
            }&lt;br /&gt;
            .font(.largeTitle)&lt;br /&gt;
            .foregroundColor(.white)&lt;br /&gt;
            .background(&lt;br /&gt;
                Capsule()&lt;br /&gt;
                    .foregroundColor(Color.blue)&lt;br /&gt;
                    .frame(width: 200, height: 60, alignment: .center)&lt;br /&gt;
            )&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
===Toggle(@State)===&lt;br /&gt;
----&lt;br /&gt;
[[File:swift_sample_toggle.png|200px]]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import SwiftUI&lt;br /&gt;
&lt;br /&gt;
struct ToggleView: View {&lt;br /&gt;
    @State var isOn = true&lt;br /&gt;
    var body: some View {&lt;br /&gt;
        VStack {&lt;br /&gt;
            Toggle(isOn: $isOn) {&lt;br /&gt;
                Text(&amp;quot;On/Off&amp;quot;)&lt;br /&gt;
                    .font(.title)&lt;br /&gt;
            }&lt;br /&gt;
            .fixedSize()&lt;br /&gt;
            .padding()&lt;br /&gt;
            &lt;br /&gt;
            /* https://developer.apple.com/design/human-interface-guidelines/sf-symbols/overview/&lt;br /&gt;
             */&lt;br /&gt;
            Button(action: {&lt;br /&gt;
                withAnimation {&lt;br /&gt;
                    self.isOn.toggle()&lt;br /&gt;
                }&lt;br /&gt;
            }) {&lt;br /&gt;
                Image(systemName: self.isOn ? &amp;quot;applewatch&amp;quot; : &amp;quot;applewatch.slash&amp;quot;)&lt;br /&gt;
                    .font(.system(size: 60))&lt;br /&gt;
                    .frame(width: 100, height: 100)&lt;br /&gt;
                    .imageScale(.large)&lt;br /&gt;
                    .rotationEffect(.degrees(isOn ? 0 : 360))&lt;br /&gt;
                    &lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Stepper===&lt;br /&gt;
----&lt;br /&gt;
[[File:swift_sample_stepper.png|200px]]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import SwiftUI&lt;br /&gt;
&lt;br /&gt;
struct StepperView: View {&lt;br /&gt;
    @State var cnt = 0;&lt;br /&gt;
    var body: some View {&lt;br /&gt;
        VStack {&lt;br /&gt;
            Stepper(value: $cnt, in: 0 ... 5) {&lt;br /&gt;
                Text(&amp;quot;Stepper-\(self.cnt)&amp;quot;)&lt;br /&gt;
            }.frame(width: 200)&lt;br /&gt;
            Stepper(&lt;br /&gt;
                onIncrement: {&lt;br /&gt;
                    self.cnt += 5;&lt;br /&gt;
                },&lt;br /&gt;
                onDecrement: {&lt;br /&gt;
                    self.cnt -= 3;&lt;br /&gt;
                },&lt;br /&gt;
                label: {&lt;br /&gt;
                    Text(&amp;quot;Stepper-\(self.cnt)&amp;quot;)&lt;br /&gt;
                }&lt;br /&gt;
            ).frame(width: 200)&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Alert===&lt;br /&gt;
----&lt;br /&gt;
[[File:swift_sample_alert.png|200px]]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import SwiftUI&lt;br /&gt;
&lt;br /&gt;
struct AlertView: View {&lt;br /&gt;
    @State var isAlert = false;&lt;br /&gt;
    var body: some View {&lt;br /&gt;
        Button(action: {&lt;br /&gt;
            self.isAlert = true&lt;br /&gt;
        }) {&lt;br /&gt;
            Text(&amp;quot;Alert&amp;quot;)&lt;br /&gt;
                .foregroundColor(.white)&lt;br /&gt;
        }.background(&lt;br /&gt;
            Capsule()&lt;br /&gt;
                .foregroundColor(.blue)&lt;br /&gt;
                .frame(width: 100, height: 40)&lt;br /&gt;
        ).alert(isPresented: $isAlert, content: {&lt;br /&gt;
            Alert(title: Text(&amp;quot;Title&amp;quot;),message: Text(&amp;quot;Messge&amp;quot;),&lt;br /&gt;
                primaryButton: .default(Text(&amp;quot;OK&amp;quot;), action: {}),&lt;br /&gt;
                secondaryButton: .cancel(Text(&amp;quot;Cancel&amp;quot;),action: {}))&lt;br /&gt;
        })&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Tab===&lt;br /&gt;
----&lt;br /&gt;
[[File:swift_sample_tab.png|200px]]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
struct TabbedView: View {&lt;br /&gt;
    @State var selection = 0&lt;br /&gt;
    var body: some View {&lt;br /&gt;
        TabView(selection: $selection) {&lt;br /&gt;
            ButtonView().tabItem {&lt;br /&gt;
                Text(&amp;quot;Item1&amp;quot;)&lt;br /&gt;
            }.tag(1)&lt;br /&gt;
            ToggleView().tabItem {&lt;br /&gt;
                Text(&amp;quot;Item2&amp;quot;)&lt;br /&gt;
            }.tag(2)&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
====Tab切り替えイベント====&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    @State var selectedTabIndex = 1;&lt;br /&gt;
    var body: some View {&lt;br /&gt;
        TabView(selection: $selectedTabIndex) {&lt;br /&gt;
            arpListView.tabItem {&lt;br /&gt;
                Text(&amp;quot;Tab Label 1&amp;quot;)&lt;br /&gt;
            }.tag(1)&lt;br /&gt;
            hostListView.tabItem {&lt;br /&gt;
                Text(&amp;quot;Tab Label 2&amp;quot;)&lt;br /&gt;
            }.tag(2)&lt;br /&gt;
        }&lt;br /&gt;
        .onChange(of: selectedTabIndex) { value in&lt;br /&gt;
            print(&amp;quot;TAB INDEX \(value)&amp;quot;)&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Binding===&lt;br /&gt;
----&lt;br /&gt;
[[File:swift_sample_binding.png|200px]]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import SwiftUI&lt;br /&gt;
&lt;br /&gt;
struct BindingView: View {&lt;br /&gt;
    @State var isChecked1: Bool = false&lt;br /&gt;
    @State var isChecked2: Bool = false&lt;br /&gt;
    var body: some View {&lt;br /&gt;
        VStack {&lt;br /&gt;
            CheckImageButton(isChecked: $isChecked1)&lt;br /&gt;
            CheckImageButton(isChecked: $isChecked2)&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
struct CheckImageButton: View {&lt;br /&gt;
    @Binding var isChecked: Bool&lt;br /&gt;
    var body: some View {&lt;br /&gt;
        Button(action: {&lt;br /&gt;
            self.isChecked.toggle()&lt;br /&gt;
        }) {&lt;br /&gt;
            Image(systemName: isChecked ?&lt;br /&gt;
                &amp;quot;person.crop.circle.badge.checkmark&amp;quot;:&lt;br /&gt;
                &amp;quot;person.crop.circle&amp;quot;)&lt;br /&gt;
                .foregroundColor(&lt;br /&gt;
                    isChecked ? .blue : .gray)&lt;br /&gt;
        }&lt;br /&gt;
        .imageScale(.large)&lt;br /&gt;
        .frame(width: 40)&lt;br /&gt;
    &lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
====リストのBinding====&lt;br /&gt;
----&lt;br /&gt;
[[File:swiftui_binding_list.png|500px]]&lt;br /&gt;
&lt;br /&gt;
*Model&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import Foundation&lt;br /&gt;
import AppKit&lt;br /&gt;
import SwiftUI&lt;br /&gt;
&lt;br /&gt;
class File : Identifiable, ObservableObject {&lt;br /&gt;
    let id = UUID()&lt;br /&gt;
    let path: String&lt;br /&gt;
    let name: String&lt;br /&gt;
    let isDirectory: Bool&lt;br /&gt;
    var isOn: Bool = false&lt;br /&gt;
    &lt;br /&gt;
    init(path: String, name: String, isDirectory: Bool, isOn: Bool) {&lt;br /&gt;
        self.path = path&lt;br /&gt;
        self.name = name&lt;br /&gt;
        self.isDirectory = isDirectory&lt;br /&gt;
        self.isOn = isOn&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
class FileList : ObservableObject {&lt;br /&gt;
    @Published var files: [File] = []&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
*UI&lt;br /&gt;
**各所(①②③)に$をつける&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import SwiftUI&lt;br /&gt;
&lt;br /&gt;
struct ContentView: View {&lt;br /&gt;
    @ObservedObject var filePaths = FileList()&lt;br /&gt;
    @State private var selectedPaths = Set&amp;lt;File.ID&amp;gt;()&lt;br /&gt;
    &lt;br /&gt;
    var body: some View {&lt;br /&gt;
        Button(action: {&lt;br /&gt;
            let rootDir = EncConverterService.chooseDir()&lt;br /&gt;
            let queue = DispatchQueue.global(qos: .userInitiated)&lt;br /&gt;
            queue.async {&lt;br /&gt;
                EncConverterService.loadFile(directoryPath: rootDir, filepaths: self.filePaths)&lt;br /&gt;
            }&lt;br /&gt;
        }) {&lt;br /&gt;
            Text(&amp;quot;Choose dir&amp;quot;)  &lt;br /&gt;
        }&lt;br /&gt;
        &lt;br /&gt;
        Table($filePaths.files, selection: $selectedPaths) {   // ①&lt;br /&gt;
            TableColumn(&amp;quot;path&amp;quot;) { $file in  // ②&lt;br /&gt;
                let isDir = file.isDirectory&lt;br /&gt;
                HStack {&lt;br /&gt;
                    if !isDir {&lt;br /&gt;
                        Toggle(&amp;quot;&amp;quot;,isOn: $file.isOn) //　③&lt;br /&gt;
                            .padding(.leading, (isDir) ? 0 : 20)&lt;br /&gt;
                    }&lt;br /&gt;
                    Text((isDir) ? file.path : file.name)&lt;br /&gt;
                        .font((isDir) ? .headline : .none)&lt;br /&gt;
                        &lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
        Text(&amp;quot;\(selectedPaths.count) path selected&amp;quot;)&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===画像===&lt;br /&gt;
----&lt;br /&gt;
[[File:Swiftui image sample.png|600px]]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import SwiftUI&lt;br /&gt;
&lt;br /&gt;
struct ContentView: View {&lt;br /&gt;
    var body: some View {&lt;br /&gt;
        VStack {&lt;br /&gt;
            Image(&amp;quot;add_component_swiftui&amp;quot;).resizable()&lt;br /&gt;
                .aspectRatio(contentMode:.fill)&lt;br /&gt;
                .frame(width: 400, height: 400)&lt;br /&gt;
                .scaleEffect(1.2)&lt;br /&gt;
                .offset(x: -60, y: 0)&lt;br /&gt;
                .clipped()&lt;br /&gt;
                .overlay(&lt;br /&gt;
                    Text(&amp;quot;SwiftUI Sample&amp;quot;)&lt;br /&gt;
                        .font(.title)&lt;br /&gt;
                        .foregroundColor(.red)&lt;br /&gt;
                )&lt;br /&gt;
                .clipShape(Circle()/)&lt;br /&gt;
                .shadow(radius: 10)&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
struct ContentView_Previews: PreviewProvider {&lt;br /&gt;
    static var previews: some View {&lt;br /&gt;
        ContentView()&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===図形===&lt;br /&gt;
----&lt;br /&gt;
[[File:Swiftui_sample_figure.png|600px]]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import SwiftUI&lt;br /&gt;
&lt;br /&gt;
struct Figure: View {&lt;br /&gt;
    var body: some View {&lt;br /&gt;
          VStack {&lt;br /&gt;
              Circle()&lt;br /&gt;
                  .foregroundColor(.blue)&lt;br /&gt;
                  .frame(width: 100.0, height:100.0)&lt;br /&gt;
              Ellipse()&lt;br /&gt;
                  .foregroundColor(.green)&lt;br /&gt;
                  .frame(width: 200, height: 100.0)&lt;br /&gt;
              Rectangle()&lt;br /&gt;
                  .foregroundColor(.orange)&lt;br /&gt;
                  .frame(width: 100.0, height: 100.0)&lt;br /&gt;
                  .rotationEffect(.degrees(45))&lt;br /&gt;
            }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
struct Figure_Previews: PreviewProvider {&lt;br /&gt;
    static var previews: some View {&lt;br /&gt;
        Figure()&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===List===&lt;br /&gt;
----&lt;br /&gt;
[[File:Swiftui_list_sample.png|600px]]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import SwiftUI&lt;br /&gt;
&lt;br /&gt;
struct ListView: View {&lt;br /&gt;
    var body: some View {&lt;br /&gt;
        NavigationView {&lt;br /&gt;
            List {&lt;br /&gt;
                Text(&amp;quot;List Item&amp;quot;)&lt;br /&gt;
                Text(&amp;quot;List Item&amp;quot;)&lt;br /&gt;
                HStack {&lt;br /&gt;
                    Image(&amp;quot;add_component_swiftui&amp;quot;)&lt;br /&gt;
                        .frame(width: 100, height: 100)&lt;br /&gt;
                        .scaleEffect(0.2)&lt;br /&gt;
                        .aspectRatio(contentMode:.fit)&lt;br /&gt;
                        .clipped()&lt;br /&gt;
                        .clipShape(/*@START_MENU_TOKEN@*/Circle()/*@END_MENU_TOKEN@*/)&lt;br /&gt;
                       &lt;br /&gt;
                }&lt;br /&gt;
                Text(&amp;quot;List Item&amp;quot;)&lt;br /&gt;
                Text(&amp;quot;List Item&amp;quot;)&lt;br /&gt;
            }.navigationBarTitle(&amp;quot;List Title&amp;quot;)&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
struct ListView_Previews: PreviewProvider {&lt;br /&gt;
    static var previews: some View {&lt;br /&gt;
        ListView()&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====List(繰り返し、Section)====&lt;br /&gt;
----&lt;br /&gt;
[[File:Swiftui_list_section.png|600px]]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import SwiftUI&lt;br /&gt;
&lt;br /&gt;
let items = [&amp;quot;item1&amp;quot;,&amp;quot;item2&amp;quot;,&amp;quot;item3&amp;quot;,&amp;quot;item4&amp;quot;,&amp;quot;item5&amp;quot;];&lt;br /&gt;
struct EmbededList: View {&lt;br /&gt;
    var body: some View {&lt;br /&gt;
        VStack {&lt;br /&gt;
            List(0..&amp;lt;items.count) { idx in&lt;br /&gt;
                Text(items[idx])&lt;br /&gt;
            }&lt;br /&gt;
            .frame(height: 300.0)&lt;br /&gt;
            List {&lt;br /&gt;
                Section(header: Text(&amp;quot;Section1&amp;quot;)) {&lt;br /&gt;
                    ForEach(0 ..&amp;lt; items.count) { idx in&lt;br /&gt;
                        Text(items[idx])&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
                Section(header: Text(&amp;quot;Section2&amp;quot;)) {&lt;br /&gt;
                    ForEach(0 ..&amp;lt; items.count) { idx in&lt;br /&gt;
                        Text(items[idx])&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
struct EmbededList_Previews: PreviewProvider {&lt;br /&gt;
    static var previews: some View {&lt;br /&gt;
        EmbededList()&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Listにオブジェクトを表示====&lt;br /&gt;
----&lt;br /&gt;
[[File:swift_ui_object_load_to_list.png|500px]]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import SwiftUI&lt;br /&gt;
&lt;br /&gt;
struct ContentView: View {&lt;br /&gt;
    @ObservedObject var hosts = HostList()&lt;br /&gt;
    var body: some View {&lt;br /&gt;
        VStack {&lt;br /&gt;
            HStack {&lt;br /&gt;
                Button(action: {&lt;br /&gt;
                    WoLService().arp(hosts:self.hosts)&lt;br /&gt;
                }) {&lt;br /&gt;
                    Text(&amp;quot;arp -a&amp;quot;)&lt;br /&gt;
                }.padding()&lt;br /&gt;
            }&lt;br /&gt;
            Divider()&lt;br /&gt;
            List (hosts.hosts, id: \.ip){ host in&lt;br /&gt;
                Text(host.host)&lt;br /&gt;
                Text(host.ip)&lt;br /&gt;
                Text(host.macaddr)&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
*&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import Foundation&lt;br /&gt;
&lt;br /&gt;
class HostList : ObservableObject {&lt;br /&gt;
    @Published var hosts: [Host] = []&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
class Host {&lt;br /&gt;
    var host: String = &amp;quot;&amp;quot;&lt;br /&gt;
    var ip: String = &amp;quot;&amp;quot;&lt;br /&gt;
    var macaddr: String = &amp;quot;&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
===Table===&lt;br /&gt;
----&lt;br /&gt;
*https://developer.apple.com/documentation/swiftui/table&lt;br /&gt;
&lt;br /&gt;
[[File:swiftui_tableview.png|500px]]&lt;br /&gt;
&lt;br /&gt;
*Service&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import Foundation&lt;br /&gt;
import AppKit&lt;br /&gt;
import SwiftUI&lt;br /&gt;
&lt;br /&gt;
class File : Identifiable {&lt;br /&gt;
    let id = UUID()&lt;br /&gt;
    let path: String&lt;br /&gt;
    &lt;br /&gt;
    init(path: String) {&lt;br /&gt;
        self.path = path&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
class FileList : ObservableObject {&lt;br /&gt;
    @Published var files: [File] = []&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
public struct EncConverterService {&lt;br /&gt;
    static func chooseDir() -&amp;gt; String {&lt;br /&gt;
        &lt;br /&gt;
        let dialog = NSOpenPanel();&lt;br /&gt;
&lt;br /&gt;
        dialog.title                   = &amp;quot;Choose a file| Our Code World&amp;quot;&lt;br /&gt;
        dialog.showsResizeIndicator    = true&lt;br /&gt;
        dialog.showsHiddenFiles        = false&lt;br /&gt;
        dialog.allowsMultipleSelection = false&lt;br /&gt;
        dialog.canChooseDirectories    = true&lt;br /&gt;
        dialog.canChooseFiles          = false&lt;br /&gt;
&lt;br /&gt;
        if (dialog.runModal() ==  NSApplication.ModalResponse.OK) {&lt;br /&gt;
            let result = dialog.url&lt;br /&gt;
&lt;br /&gt;
            if (result != nil) {&lt;br /&gt;
                let path: String = result!.path&lt;br /&gt;
                return path&lt;br /&gt;
            }&lt;br /&gt;
            &lt;br /&gt;
        }&lt;br /&gt;
        return &amp;quot;&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    static func loadFile(directoryPath: String, filepaths: FileList) {&lt;br /&gt;
        print(directoryPath)&lt;br /&gt;
        filepaths.files.append(File(path: directoryPath))&lt;br /&gt;
        do {&lt;br /&gt;
            let fm = FileManager.default&lt;br /&gt;
            let fileNames = try fm.contentsOfDirectory(atPath: directoryPath)&lt;br /&gt;
            &lt;br /&gt;
            for fileName in fileNames {&lt;br /&gt;
                let childPath = directoryPath + &amp;quot;/&amp;quot; + fileName&lt;br /&gt;
                &lt;br /&gt;
                var isDir = ObjCBool(false)&lt;br /&gt;
                fm.fileExists(atPath: childPath, isDirectory: &amp;amp;isDir)&lt;br /&gt;
                if isDir.boolValue {&lt;br /&gt;
                    loadFile(directoryPath: childPath, filepaths: filepaths)&lt;br /&gt;
                }&lt;br /&gt;
                print(&amp;quot;\t&amp;quot; + childPath)&lt;br /&gt;
                filepaths.files.append(File(path: childPath))&lt;br /&gt;
            }&lt;br /&gt;
        } catch {&lt;br /&gt;
            print(error)&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
*View&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import SwiftUI&lt;br /&gt;
&lt;br /&gt;
struct ContentView: View {&lt;br /&gt;
    @ObservedObject var filePaths = FileList()&lt;br /&gt;
    @State private var selectedPaths = Set&amp;lt;File.ID&amp;gt;()&lt;br /&gt;
    &lt;br /&gt;
    var body: some View {&lt;br /&gt;
        Button(action: {&lt;br /&gt;
            let rootDir = EncConverterService.chooseDir()&lt;br /&gt;
            let queue = DispatchQueue.global(qos: .userInitiated)&lt;br /&gt;
            queue.async {&lt;br /&gt;
                EncConverterService.loadFile(directoryPath: rootDir, filepaths: self.filePaths)&lt;br /&gt;
            }&lt;br /&gt;
        }) {&lt;br /&gt;
            Text(&amp;quot;Choose dir&amp;quot;)&lt;br /&gt;
        }&lt;br /&gt;
        &lt;br /&gt;
        Table(filePaths.files, selection: $selectedPaths) {&lt;br /&gt;
            TableColumn(&amp;quot;Path&amp;quot;, value: \.path)&lt;br /&gt;
        }&lt;br /&gt;
        Text(&amp;quot;\(selectedPaths.count) path selected&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==コードサンプル(ロジック)==&lt;br /&gt;
&lt;br /&gt;
===Observable(@ObservedObject,@Published,@State)===&lt;br /&gt;
----&lt;br /&gt;
#データクラスはObservableObjectプロトコル準拠とする。&lt;br /&gt;
#監視対象とするプロパティに@Published属性を付加する。&lt;br /&gt;
#&amp;lt;u&amp;gt;データクラスのインスタンスは@ObservedObject属性を付加してViewの中で宣言する&amp;lt;/u&amp;gt;&lt;br /&gt;
[[File:swift_sample_observable.png|200px]]&lt;br /&gt;
*Publish&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import Foundation&lt;br /&gt;
&lt;br /&gt;
class PublishObject: ObservableObject {&lt;br /&gt;
    @Published var counter: Int = 0&lt;br /&gt;
    &lt;br /&gt;
    var timer = Timer()&lt;br /&gt;
    &lt;br /&gt;
    func start() {&lt;br /&gt;
        timer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { _ in&lt;br /&gt;
            self.counter += 1&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    func stop() {&lt;br /&gt;
        timer.invalidate()&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    func reset() {&lt;br /&gt;
        timer.invalidate()&lt;br /&gt;
        counter = 0&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
*Subscribe&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import SwiftUI&lt;br /&gt;
&lt;br /&gt;
struct SubscriberView: View {&lt;br /&gt;
    @ObservedObject var publisher = PublishObject()&lt;br /&gt;
    &lt;br /&gt;
    let currentTimer = Timer.TimerPublisher(interval: 1.0, runLoop: .main, mode: .default).autoconnect()&lt;br /&gt;
    @State var now = Date()&lt;br /&gt;
    &lt;br /&gt;
    var body: some View {&lt;br /&gt;
        VStack {&lt;br /&gt;
            Text(&amp;quot;\(self.now.description)&amp;quot;)&lt;br /&gt;
            HStack {&lt;br /&gt;
                Button(action: {&lt;br /&gt;
                    self.publisher.start()&lt;br /&gt;
                }){&lt;br /&gt;
                    Image(systemName: &amp;quot;play&amp;quot;)&lt;br /&gt;
                }.padding()&lt;br /&gt;
                Button(action: {&lt;br /&gt;
                    self.publisher.stop()&lt;br /&gt;
                }){&lt;br /&gt;
                    Image(systemName: &amp;quot;pause&amp;quot;)&lt;br /&gt;
                }.padding()&lt;br /&gt;
                Button(action: {&lt;br /&gt;
                    self.publisher.reset()&lt;br /&gt;
                }){&lt;br /&gt;
                    Image(systemName: &amp;quot;backward.end&amp;quot;)&lt;br /&gt;
                }.padding()&lt;br /&gt;
            }&lt;br /&gt;
            .frame(width:200)&lt;br /&gt;
        &lt;br /&gt;
            Text(&amp;quot;\(self.publisher.counter)&amp;quot;)&lt;br /&gt;
            &lt;br /&gt;
        }.font(.largeTitle)&lt;br /&gt;
        .onReceive(currentTimer) { date in&lt;br /&gt;
            self.now = date&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
===動的に検索===&lt;br /&gt;
[[File:swiftui_dynamic_search.png|400px]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
struct HostListView: View {&lt;br /&gt;
    @ObservedObject var hosts = HostList()&lt;br /&gt;
    @ObservedObject var param = HostViewParameter()&lt;br /&gt;
    // 検索キーワード&lt;br /&gt;
    @State var searchKeyword = &amp;quot;&amp;quot;&lt;br /&gt;
    &lt;br /&gt;
    var body: some View {&lt;br /&gt;
        VStack {&lt;br /&gt;
            let columns =&lt;br /&gt;
                [GridItem(.adaptive(minimum: 250, maximum: 800))]&lt;br /&gt;
            ScrollView {&lt;br /&gt;
                LazyVGrid(columns: columns, spacing:10) {&lt;br /&gt;
                    //　Arrayにfilterを適用&lt;br /&gt;
                    ForEach(hosts.hosts.filter({ (host) -&amp;gt; Bool in&lt;br /&gt;
                        if searchKeyword != &amp;quot;&amp;quot; {&lt;br /&gt;
                            return host.host.contains(searchKeyword) ||&lt;br /&gt;
                                host.ip.contains(searchKeyword) ||&lt;br /&gt;
                                host.comment.contains(searchKeyword)&lt;br /&gt;
                        }&lt;br /&gt;
                        return true&lt;br /&gt;
                    }), id: \.id) { host in&lt;br /&gt;
                        HostView(host:host).environmentObject(param)&lt;br /&gt;
                    }&lt;br /&gt;
                } .padding(20)&lt;br /&gt;
            }.toolbar {&lt;br /&gt;
                        :&lt;br /&gt;
               ToolbarItem(placement: .automatic) {&lt;br /&gt;
                    TextField(&amp;quot;search...&amp;quot;, text: $searchKeyword)&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===バックグラウンドからUIを操作する===&lt;br /&gt;
----&lt;br /&gt;
*observableobj が、ObservableObject の派生クラス&lt;br /&gt;
*contentフィールドに、@Published アノテーション&lt;br /&gt;
*Viewで、@ObservedObjectを付与しインスタンスを生成&lt;br /&gt;
*上記で、バックグラウンドから、observableobj.contentを操作すると、UIはメインスレッドから触るように怒られる。&lt;br /&gt;
&amp;lt;blockquote&amp;gt;Publishing changes from background threads is not allowed; make sure to publish values from the main thread (via operators like receive(on:)) on model updates.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
*DispatchQueue.main.syncで囲む&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
DispatchQueue.main.sync {&lt;br /&gt;
    observableobj.content = text&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Tips==&lt;br /&gt;
&lt;br /&gt;
===VSCode + Github Copilot で iPhone アプリ開発===&lt;br /&gt;
*https://www.typea.info/blog/index.php/2024/12/29/vscode_and_github_copilot_dev_iphone_app/&lt;br /&gt;
===[https://www.typea.info/blog/index.php/2021/11/30/swift_macos_app_permission/ ファイルパーミッションエラー（App Sandbox)]===&lt;br /&gt;
----&lt;br /&gt;
*[https://www.typea.info/blog/index.php/2021/11/30/swift_macos_app_permission/ ファイルパーミッションエラー（App Sandbox)]&lt;br /&gt;
===[https://www.typea.info/blog/index.php/2021/01/23/swiftui_tips_view_component_locate/ 画面部品の追加方法]===&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===SwiftUIライブラリ===&lt;br /&gt;
----&lt;br /&gt;
====[https://github.com/SwiftUIX/SwiftUIX SwiftUIX]====&lt;br /&gt;
[https://qiita.com/yosshi4486/items/3d92f81feaabc1049b4c SwiftUIアプリケーション開発の不足を補うSwiftUIX]&lt;br /&gt;
&lt;br /&gt;
===ファイル選択===&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 let dialog = NSOpenPanel();&lt;br /&gt;
&lt;br /&gt;
dialog.title                   = &amp;quot;Choose a file&amp;quot;&lt;br /&gt;
dialog.showsResizeIndicator    = true&lt;br /&gt;
dialog.showsHiddenFiles        = false&lt;br /&gt;
dialog.allowsMultipleSelection = false&lt;br /&gt;
dialog.canChooseDirectories = false&lt;br /&gt;
&lt;br /&gt;
if (dialog.runModal() ==  NSApplication.ModalResponse.OK) {&lt;br /&gt;
	let result = dialog.url &lt;br /&gt;
	if (result != nil) {&lt;br /&gt;
		let path: String = result!.path&lt;br /&gt;
		print(path)&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
} else {&lt;br /&gt;
	return&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Piroto</name></author>
		
	</entry>
	<entry>
		<id>https://www.typea.info/tips_/index.php?title=SwiftUI&amp;diff=35366</id>
		<title>SwiftUI</title>
		<link rel="alternate" type="text/html" href="https://www.typea.info/tips_/index.php?title=SwiftUI&amp;diff=35366"/>
		<updated>2024-12-29T07:39:17Z</updated>

		<summary type="html">&lt;p&gt;Piroto: /* Tips */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;| [[Swift]] | [[Mac]] | [[Xcode]] | [[Swift Sample]] | [[Cocoa]] | [[Xamarin.Mac]] |&lt;br /&gt;
&lt;br /&gt;
{{amazon|B082SMJC7V}}&lt;br /&gt;
&lt;br /&gt;
==SwiftUI==&lt;br /&gt;
*[https://developer.apple.com/jp/xcode/swiftui/ SwiftUI]&lt;br /&gt;
*[https://developer.apple.com/documentation/swiftui/ SwiftUI Documents]&lt;br /&gt;
*[https://www.raywenderlich.com/macos macos tutorials]&lt;br /&gt;
*1セットのツールとAPIを使用するだけで、あらゆるAppleデバイス向けのユーザーインターフェイスを構築&lt;br /&gt;
*宣言型シンタックスを使&lt;br /&gt;
*宣言型のスタイルは、アニメーションなどの複雑な概念にも適用&lt;br /&gt;
===デザインツール===&lt;br /&gt;
*Xcodeには、SwiftUIでのインターフェイス構築をドラッグ＆ドロップのように簡単に行える直感的な新しいデザインツールが含まれています&lt;br /&gt;
*デザインキャンバスでの編集内容と、隣接するエディタ内のコードはすべて完全に同期されます&lt;br /&gt;
====ドラッグ＆ドロップ====&lt;br /&gt;
*ユーザーインターフェイス内のコンポーネントの位置は、キャンバス上でコントロールをドラッグするだけで調整できます&lt;br /&gt;
====ダイナミックリプレースメント====&lt;br /&gt;
*wiftのコンパイラとランタイムはXcode全体に完全に埋め込まれているため、Appは常にビルドされ実行されます&lt;br /&gt;
*表示されるデザインキャンバスは、単にユーザーインターフェイスに似せたものではなく、実際のAppそのもの&lt;br /&gt;
*Xcodeは編集したコードを実際のAppに直接組み入れることができます&lt;br /&gt;
====プレビュー====&lt;br /&gt;
*プレビューを1つまたは複数作成して、サンプルデータを取得できる&lt;br /&gt;
&lt;br /&gt;
===Swift UI チュートリアルをやってみる===&lt;br /&gt;
----&lt;br /&gt;
*[https://www.typea.info/blog/index.php/2020/12/09/swiftui_tutorial_youtube_memo/  プロジェクト作成〜TextViewのカスタマイズ]&lt;br /&gt;
*[[Xcode]]&lt;br /&gt;
*resume -&amp;gt; プレビュー&lt;br /&gt;
*command + click -&amp;gt; Action List&lt;br /&gt;
*右上の +　ボタンでコントロール追加&lt;br /&gt;
&lt;br /&gt;
====[[Xcode]] ナビゲーター====&lt;br /&gt;
----&lt;br /&gt;
[[File:xcode_navgator_icons.png|400px]]&lt;br /&gt;
左から&lt;br /&gt;
#プロジェクトナビゲーター&lt;br /&gt;
#ソースコントロールナビゲーター&lt;br /&gt;
#シンボルナビゲーター&lt;br /&gt;
#検索ナビゲーター&lt;br /&gt;
#イシューナビゲーター&lt;br /&gt;
#テストナビゲーター&lt;br /&gt;
#デバッグナビゲーター&lt;br /&gt;
#ブレークポイントナビゲーター&lt;br /&gt;
#レポートナビゲーター&lt;br /&gt;
&lt;br /&gt;
====[https://www.typea.info/blog/index.php/2020/12/09/swiftui_tutorial_youtube_memo/  プロジェクト作成〜TextViewのカスタマイズ]====&lt;br /&gt;
====[https://www.typea.info/blog/index.php/2020/12/19/swiftui_tutorial_custom_image_view/  Custom Image Viewの作成]====&lt;br /&gt;
====[https://www.typea.info/blog/index.php/2020/12/06/xcode_macos_proguramming/  Xcodeを使ってmacOS プログラミングとplaygroundの作成]====&lt;br /&gt;
====[https://www.typea.info/blog/index.php/2021/01/23/swiftui_tutorial_list_navigation/  Listとナビゲーションとプレビュー]====&lt;br /&gt;
&lt;br /&gt;
==レイアウト==&lt;br /&gt;
===[https://d1v1b.com/swiftui/alignment Alignment]===&lt;br /&gt;
----&lt;br /&gt;
*[https://d1v1b.com/swiftui/alignment Alignment]&lt;br /&gt;
&lt;br /&gt;
===[https://t32k.me/mol/log/margin-padding-swiftui/ 余白の取り方]===&lt;br /&gt;
----&lt;br /&gt;
*[https://t32k.me/mol/log/margin-padding-swiftui/ 余白の取り方]&lt;br /&gt;
*記述箇所によって、表示が変わる&lt;br /&gt;
&lt;br /&gt;
*backgroundにpaddingを指定する（cssのmargin的な効果)&lt;br /&gt;
[[File:swiftui_padding2.png|300px]]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  Text(host.host)&lt;br /&gt;
       .background(Color.green)&lt;br /&gt;
       .padding()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
*Textにpaddingを指定することになる(cssのpadding的効果)&lt;br /&gt;
[[File:swiftui_padding1.png|300px]]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  Text(host.host)&lt;br /&gt;
       .padding()&lt;br /&gt;
       .background(Color.green)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===ボタンサイズ===&lt;br /&gt;
----&lt;br /&gt;
*ボタンのサイズを内容にフィットさせたい&lt;br /&gt;
[[File:swiftui_button_size1.png|300px]]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  Button(action: {}) {&lt;br /&gt;
     VStack{&lt;br /&gt;
         :&lt;br /&gt;
     }&lt;br /&gt;
    .padding()&lt;br /&gt;
    .border(Color.blue, width: 3)&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
*.buttonStyle(PlainButtonStyle()) を指定&lt;br /&gt;
[[File:swiftui_button_size2.png|300px]]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Button(action: {}) {&lt;br /&gt;
   VStack{&lt;br /&gt;
         :&lt;br /&gt;
     }&lt;br /&gt;
    .padding()&lt;br /&gt;
    .border(Color.blue, width: 3)&lt;br /&gt;
}.buttonStyle(PlainButtonStyle())&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
===親Viewのサイズ情報を取得する===&lt;br /&gt;
----&lt;br /&gt;
*https://qiita.com/masa7351/items/0567969f93cc88d714ac&lt;br /&gt;
*https://www.hackingwithswift.com/quick-start/swiftui/how-to-make-two-views-the-same-width-or-height&lt;br /&gt;
[[File:swiftui_grid_layout1.png|200px]]&lt;br /&gt;
[[File:swiftui_grid_layout2.png|400px]]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
struct HostView : View {&lt;br /&gt;
    var host: WoL.Host&lt;br /&gt;
    var body: some View {&lt;br /&gt;
        GeometryReader { geo in&lt;br /&gt;
            HStack() {&lt;br /&gt;
                Text(host.host)&lt;br /&gt;
                    .padding()&lt;br /&gt;
                    .frame(width:  geo.size.width * 0.33 , alignment: .leading)&lt;br /&gt;
                    .frame(maxHeight: .infinity)&lt;br /&gt;
                    .background(Color.red)&lt;br /&gt;
                Text(host.ip)&lt;br /&gt;
                    .padding()&lt;br /&gt;
                    .frame(width: geo.size.width * 0.33 , alignment: .leading)&lt;br /&gt;
                    .frame(maxHeight: .infinity)&lt;br /&gt;
                    .background(Color.green)&lt;br /&gt;
                Text(host.macaddr)&lt;br /&gt;
                    .padding()&lt;br /&gt;
                    .frame(width: geo.size.width * 0.33 , alignment: .leading)&lt;br /&gt;
                    .frame(maxHeight: .infinity)&lt;br /&gt;
                    .background(Color.yellow)&lt;br /&gt;
            }.fixedSize(horizontal: false, vertical: true)&lt;br /&gt;
            &lt;br /&gt;
        }.frame(height: 60)&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===影をつける===&lt;br /&gt;
---&lt;br /&gt;
*shadowを設定すると、内部のコンポーネント全てに影がつく、compositingGroup を指定することで、背景だけに影をつけることができる&lt;br /&gt;
&amp;lt;pre&amp;gt;   &lt;br /&gt;
             :&lt;br /&gt;
        .background()&lt;br /&gt;
        .compositingGroup()&lt;br /&gt;
        .shadow(radius: 10)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
===Card View===&lt;br /&gt;
----&lt;br /&gt;
*[https://www.hackingwithswift.com/books/ios-swiftui/designing-a-single-card-view Card View]&lt;br /&gt;
*LazyGrid &lt;br /&gt;
[[File:swiftui_card_layout1.png|400px]]&lt;br /&gt;
[[File:swiftui_card_layout2.png|200px]]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
            let columns =&lt;br /&gt;
                [GridItem(.adaptive(minimum: 250, maximum: 800))]&lt;br /&gt;
            ScrollView {&lt;br /&gt;
                LazyVGrid(columns: columns, spacing:10) {&lt;br /&gt;
                    ForEach(hosts.hosts, id: \.macaddr) { host in&lt;br /&gt;
                        HostView(host:host)&lt;br /&gt;
                    }&lt;br /&gt;
                } .padding(20)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Toolbar===&lt;br /&gt;
----&lt;br /&gt;
[[File:swiftui_toolbar.png|300lx]]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ScrollView {&lt;br /&gt;
	LazyVGrid(columns: columns) {&lt;br /&gt;
		ForEach(hosts.hosts, id: \.ip) { host in&lt;br /&gt;
			HostView(host:host)&lt;br /&gt;
		}&lt;br /&gt;
	} .padding(20)&lt;br /&gt;
}.toolbar {&lt;br /&gt;
	ToolbarItem(placement: .automatic) {&lt;br /&gt;
		Button(&amp;quot;arp -a&amp;quot;) {&lt;br /&gt;
			WoLService().arp(hosts:self.hosts)&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	ToolbarItem(placement: .automatic) {&lt;br /&gt;
		Button(&amp;quot;load&amp;quot;) {&lt;br /&gt;
			WoLService().load(hosts:self.hosts)&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==データ==&lt;br /&gt;
=== データ変更に応じて画面に反映させる ===&lt;br /&gt;
* 画面の構造体の中でデータを保持しているクラスのインスタンスを格納するプロパティに、@ObservedObjectプロパティラッパーを付与する&lt;br /&gt;
*　データを保持しているクラスを、@ObservableObjectプロトコルに準拠させる&lt;br /&gt;
* クラスの中で変更を反映させる値を保持しているプロパティに、@Publishedプロパティラッパーを付与する&lt;br /&gt;
&lt;br /&gt;
=== UserDefaults===&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===ドキュメントパス===&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)&lt;br /&gt;
print(&amp;quot;Document path: \(paths)&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
*出力&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Document path: [file:///Users/hirotoyagi/Library/Containers/info.typea.WoL/Data/Documents/]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
====ファイル格納先====&lt;br /&gt;
----&lt;br /&gt;
*[https://qiita.com/am10/items/3b2eb3d9f6c6955455b6 ファイル格納先]&lt;br /&gt;
===View間データ受け渡し===&lt;br /&gt;
----&lt;br /&gt;
SwiftUIでは親ビューと子ビュー間で値を渡す方法は、下記の3つが挙げられます。&lt;br /&gt;
&lt;br /&gt;
#Environment&lt;br /&gt;
##Viewが持つ環境変数。独自の環境変数を定義することができ、それを利用して親ビューから任意の値を渡すことが可能&lt;br /&gt;
#EnvironmentObjects&lt;br /&gt;
##他の２つに比べて一般的な方法。利用するためには独自のクラスを定義&lt;br /&gt;
#Preferences&lt;br /&gt;
##Preferenceは子から親へ伝達させる方法&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*https://qiita.com/noby111/items/26405bd89075c841029a&lt;br /&gt;
====ObservableObject を経由して親子ViewでAlertの表示フラグを共有====&lt;br /&gt;
[[File:swiftui_share_object.png|300px]]&lt;br /&gt;
*ObservableObjectを共有して、変更をSubscribeする&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
struct HostListView: View {&lt;br /&gt;
    @ObservedObject var hosts = HostList()&lt;br /&gt;
    @ObservedObject var param = Param()&lt;br /&gt;
    var body: some View {&lt;br /&gt;
        VStack {&lt;br /&gt;
            let columns =&lt;br /&gt;
                [GridItem(.adaptive(minimum: 250, maximum: 800))]&lt;br /&gt;
            ScrollView {&lt;br /&gt;
                LazyVGrid(columns: columns, spacing:10) {&lt;br /&gt;
                    ForEach(hosts.hosts, id: \.id) { host in&lt;br /&gt;
                        HostView(host:host).environmentObject(param)&lt;br /&gt;
                    }&lt;br /&gt;
                } .padding(20)&lt;br /&gt;
            }.alert(isPresented: $param.isSaveAlert, content: {&lt;br /&gt;
                Alert(title: Text(&amp;quot;Title&amp;quot;),message: Text(&amp;quot;Messge&amp;quot;),&lt;br /&gt;
                    primaryButton: .default(Text(&amp;quot;OK&amp;quot;), action: {}),&lt;br /&gt;
                    secondaryButton: .cancel(Text(&amp;quot;Cancel&amp;quot;),action: {}))&lt;br /&gt;
            })&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
struct HostView : View {&lt;br /&gt;
    @ObservedObject var host: WoL.Host&lt;br /&gt;
    @EnvironmentObject var param: Param&lt;br /&gt;
    &lt;br /&gt;
    var body: some View {&lt;br /&gt;
        VStack{&lt;br /&gt;
            HStack {&lt;br /&gt;
                Button(action: {&lt;br /&gt;
                    self.param.isSaveAlert = true&lt;br /&gt;
                }) {&lt;br /&gt;
                    Image(systemName: &amp;quot;square.and.arrow.down&amp;quot;)&lt;br /&gt;
                }.help(Text(&amp;quot;save&amp;quot;))&lt;br /&gt;
            }&lt;br /&gt;
               :            &lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
class Param : ObservableObject {&lt;br /&gt;
    @Published var isSaveAlert: Bool = false&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====@Binding を経由して親子ViewでAlertの表示フラグを共有====&lt;br /&gt;
[[File:swiftui_share_object.png|300px]]&lt;br /&gt;
*@Binding でView間で変数を共有&lt;br /&gt;
*呼び出し側は＠State&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
struct HostListView: View {&lt;br /&gt;
    @ObservedObject var hosts = HostList()&lt;br /&gt;
    @State var isSaveAlert = false&lt;br /&gt;
&lt;br /&gt;
    var body: some View {&lt;br /&gt;
        VStack {&lt;br /&gt;
            let columns =&lt;br /&gt;
                [GridItem(.adaptive(minimum: 250, maximum: 800))]&lt;br /&gt;
            ScrollView {&lt;br /&gt;
                LazyVGrid(columns: columns, spacing:10) {&lt;br /&gt;
                    ForEach(hosts.hosts, id: \.id) { host in&lt;br /&gt;
                        HostView(host:host, isSaveAlert: $isSaveAlert, alertMessage: $alertMessage)&lt;br /&gt;
                    }&lt;br /&gt;
                } .padding(20)&lt;br /&gt;
            }.alert(isPresented: $isSaveAlert, content: {&lt;br /&gt;
                Alert(title: Text(&amp;quot;Title&amp;quot;),message: Text(alertMessage),&lt;br /&gt;
                      primaryButton: .default(Text(&amp;quot;OK&amp;quot;), action: {}),&lt;br /&gt;
                      secondaryButton: .cancel(Text(&amp;quot;Cancel&amp;quot;),action: {}))&lt;br /&gt;
            })&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
struct HostView : View {&lt;br /&gt;
    @ObservedObject var host: WoL.Host&lt;br /&gt;
    @Binding var isSaveAlert: Bool&lt;br /&gt;
    &lt;br /&gt;
    var body: some View {&lt;br /&gt;
        VStack{&lt;br /&gt;
            HStack {&lt;br /&gt;
                Button(action: {&lt;br /&gt;
                    self.isSaveAlert = true&lt;br /&gt;
                }) {&lt;br /&gt;
                    Image(systemName: &amp;quot;square.and.arrow.down&amp;quot;)&lt;br /&gt;
                }.help(Text(&amp;quot;save&amp;quot;))&lt;br /&gt;
                 :&lt;br /&gt;
			}&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
=====@Binding使用時のPreview=====&lt;br /&gt;
*＠Stateかつ、staticで宣言&lt;br /&gt;
*$で変数を渡す&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
struct HostView_Previews: PreviewProvider {&lt;br /&gt;
    @State static var isAlert = true&lt;br /&gt;
&lt;br /&gt;
    static var previews: some View {&lt;br /&gt;
        let host = WoL.Host(host: &amp;quot;test.local&amp;quot;, ip: &amp;quot;192.168.0.1&amp;quot;, macaddr: &amp;quot;aa:bb:cc:dd:ee:ff&amp;quot;, comment: &amp;quot;&amp;quot;)&lt;br /&gt;
        HostView(host: host, isAlert: $isAlert)&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==メニュー==&lt;br /&gt;
===メインメニューに別のViewを開くメニューを追加===&lt;br /&gt;
----&lt;br /&gt;
[[File:swift_ui_main_menu.png|400px]]&lt;br /&gt;
*.commandsを記述&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
@main&lt;br /&gt;
struct WoLApp: App {&lt;br /&gt;
    var body: some Scene {&lt;br /&gt;
        WindowGroup {&lt;br /&gt;
            ContentView()&lt;br /&gt;
        }.commands {&lt;br /&gt;
            CommandGroup(after: CommandGroupPlacement.appInfo) {&lt;br /&gt;
                Divider()&lt;br /&gt;
                NavigationLink(destination: PreferenceView()) {&lt;br /&gt;
                    Text(&amp;quot;preferences&amp;quot;)&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==図形==&lt;br /&gt;
===Capsule===&lt;br /&gt;
----&lt;br /&gt;
[[File:swiftui_capsule.png|200px]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
VStack{&lt;br /&gt;
   :&lt;br /&gt;
}&lt;br /&gt;
.padding()&lt;br /&gt;
.background(&lt;br /&gt;
	Capsule(style: .continuous)&lt;br /&gt;
		.foregroundColor(Color.white)&lt;br /&gt;
)&lt;br /&gt;
.shadow(radius:10 )&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===RoundedRectangle===&lt;br /&gt;
----&lt;br /&gt;
[[File:swiftui_roundedRectangle.png|200px]]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
VStack{&lt;br /&gt;
  :&lt;br /&gt;
}&lt;br /&gt;
.padding()&lt;br /&gt;
.background(&lt;br /&gt;
	RoundedRectangle(cornerRadius: 20)&lt;br /&gt;
		.foregroundColor(Color.white)&lt;br /&gt;
)&lt;br /&gt;
.shadow(radius:10 )&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==画像==&lt;br /&gt;
===SF Symbol アイコン===&lt;br /&gt;
----&lt;br /&gt;
*https://developer.apple.com/design/human-interface-guidelines/sf-symbols/overview/&lt;br /&gt;
*[https://developer.apple.com/sf-symbols/ SF Symbols アプリ]&lt;br /&gt;
&lt;br /&gt;
==コードサンプル(コンポーネント)==&lt;br /&gt;
===Button===&lt;br /&gt;
----&lt;br /&gt;
[[File:swift_sample_button.png|200px]]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import Foundation&lt;br /&gt;
import SwiftUI&lt;br /&gt;
&lt;br /&gt;
struct ButtonView: View {&lt;br /&gt;
&lt;br /&gt;
    @State var cnt:Int = 0;&lt;br /&gt;
    var body: some View {&lt;br /&gt;
        VStack {&lt;br /&gt;
            Button(action: {&lt;br /&gt;
                self.cnt += 1;&lt;br /&gt;
                print(&amp;quot;print \(self.cnt)&amp;quot;)&lt;br /&gt;
            })&lt;br /&gt;
            {&lt;br /&gt;
                Text(&amp;quot;Button+1 (\(self.cnt))&amp;quot;)&lt;br /&gt;
            }&lt;br /&gt;
            .padding(.horizontal, 25.0)&lt;br /&gt;
            .font(.largeTitle)&lt;br /&gt;
            .foregroundColor(Color.white)&lt;br /&gt;
            .background(Color.green)&lt;br /&gt;
            .cornerRadius(15, antialiased: true)&lt;br /&gt;
            Divider()&lt;br /&gt;
            Button(&amp;quot;Button+2 (\(self.cnt))&amp;quot;) {&lt;br /&gt;
                self.cnt += 2;&lt;br /&gt;
            }&lt;br /&gt;
            .font(.largeTitle)&lt;br /&gt;
            .foregroundColor(.white)&lt;br /&gt;
            .background(&lt;br /&gt;
                Capsule()&lt;br /&gt;
                    .foregroundColor(Color.blue)&lt;br /&gt;
                    .frame(width: 200, height: 60, alignment: .center)&lt;br /&gt;
            )&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
===Toggle(@State)===&lt;br /&gt;
----&lt;br /&gt;
[[File:swift_sample_toggle.png|200px]]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import SwiftUI&lt;br /&gt;
&lt;br /&gt;
struct ToggleView: View {&lt;br /&gt;
    @State var isOn = true&lt;br /&gt;
    var body: some View {&lt;br /&gt;
        VStack {&lt;br /&gt;
            Toggle(isOn: $isOn) {&lt;br /&gt;
                Text(&amp;quot;On/Off&amp;quot;)&lt;br /&gt;
                    .font(.title)&lt;br /&gt;
            }&lt;br /&gt;
            .fixedSize()&lt;br /&gt;
            .padding()&lt;br /&gt;
            &lt;br /&gt;
            /* https://developer.apple.com/design/human-interface-guidelines/sf-symbols/overview/&lt;br /&gt;
             */&lt;br /&gt;
            Button(action: {&lt;br /&gt;
                withAnimation {&lt;br /&gt;
                    self.isOn.toggle()&lt;br /&gt;
                }&lt;br /&gt;
            }) {&lt;br /&gt;
                Image(systemName: self.isOn ? &amp;quot;applewatch&amp;quot; : &amp;quot;applewatch.slash&amp;quot;)&lt;br /&gt;
                    .font(.system(size: 60))&lt;br /&gt;
                    .frame(width: 100, height: 100)&lt;br /&gt;
                    .imageScale(.large)&lt;br /&gt;
                    .rotationEffect(.degrees(isOn ? 0 : 360))&lt;br /&gt;
                    &lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Stepper===&lt;br /&gt;
----&lt;br /&gt;
[[File:swift_sample_stepper.png|200px]]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import SwiftUI&lt;br /&gt;
&lt;br /&gt;
struct StepperView: View {&lt;br /&gt;
    @State var cnt = 0;&lt;br /&gt;
    var body: some View {&lt;br /&gt;
        VStack {&lt;br /&gt;
            Stepper(value: $cnt, in: 0 ... 5) {&lt;br /&gt;
                Text(&amp;quot;Stepper-\(self.cnt)&amp;quot;)&lt;br /&gt;
            }.frame(width: 200)&lt;br /&gt;
            Stepper(&lt;br /&gt;
                onIncrement: {&lt;br /&gt;
                    self.cnt += 5;&lt;br /&gt;
                },&lt;br /&gt;
                onDecrement: {&lt;br /&gt;
                    self.cnt -= 3;&lt;br /&gt;
                },&lt;br /&gt;
                label: {&lt;br /&gt;
                    Text(&amp;quot;Stepper-\(self.cnt)&amp;quot;)&lt;br /&gt;
                }&lt;br /&gt;
            ).frame(width: 200)&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Alert===&lt;br /&gt;
----&lt;br /&gt;
[[File:swift_sample_alert.png|200px]]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import SwiftUI&lt;br /&gt;
&lt;br /&gt;
struct AlertView: View {&lt;br /&gt;
    @State var isAlert = false;&lt;br /&gt;
    var body: some View {&lt;br /&gt;
        Button(action: {&lt;br /&gt;
            self.isAlert = true&lt;br /&gt;
        }) {&lt;br /&gt;
            Text(&amp;quot;Alert&amp;quot;)&lt;br /&gt;
                .foregroundColor(.white)&lt;br /&gt;
        }.background(&lt;br /&gt;
            Capsule()&lt;br /&gt;
                .foregroundColor(.blue)&lt;br /&gt;
                .frame(width: 100, height: 40)&lt;br /&gt;
        ).alert(isPresented: $isAlert, content: {&lt;br /&gt;
            Alert(title: Text(&amp;quot;Title&amp;quot;),message: Text(&amp;quot;Messge&amp;quot;),&lt;br /&gt;
                primaryButton: .default(Text(&amp;quot;OK&amp;quot;), action: {}),&lt;br /&gt;
                secondaryButton: .cancel(Text(&amp;quot;Cancel&amp;quot;),action: {}))&lt;br /&gt;
        })&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Tab===&lt;br /&gt;
----&lt;br /&gt;
[[File:swift_sample_tab.png|200px]]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
struct TabbedView: View {&lt;br /&gt;
    @State var selection = 0&lt;br /&gt;
    var body: some View {&lt;br /&gt;
        TabView(selection: $selection) {&lt;br /&gt;
            ButtonView().tabItem {&lt;br /&gt;
                Text(&amp;quot;Item1&amp;quot;)&lt;br /&gt;
            }.tag(1)&lt;br /&gt;
            ToggleView().tabItem {&lt;br /&gt;
                Text(&amp;quot;Item2&amp;quot;)&lt;br /&gt;
            }.tag(2)&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
====Tab切り替えイベント====&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    @State var selectedTabIndex = 1;&lt;br /&gt;
    var body: some View {&lt;br /&gt;
        TabView(selection: $selectedTabIndex) {&lt;br /&gt;
            arpListView.tabItem {&lt;br /&gt;
                Text(&amp;quot;Tab Label 1&amp;quot;)&lt;br /&gt;
            }.tag(1)&lt;br /&gt;
            hostListView.tabItem {&lt;br /&gt;
                Text(&amp;quot;Tab Label 2&amp;quot;)&lt;br /&gt;
            }.tag(2)&lt;br /&gt;
        }&lt;br /&gt;
        .onChange(of: selectedTabIndex) { value in&lt;br /&gt;
            print(&amp;quot;TAB INDEX \(value)&amp;quot;)&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Binding===&lt;br /&gt;
----&lt;br /&gt;
[[File:swift_sample_binding.png|200px]]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import SwiftUI&lt;br /&gt;
&lt;br /&gt;
struct BindingView: View {&lt;br /&gt;
    @State var isChecked1: Bool = false&lt;br /&gt;
    @State var isChecked2: Bool = false&lt;br /&gt;
    var body: some View {&lt;br /&gt;
        VStack {&lt;br /&gt;
            CheckImageButton(isChecked: $isChecked1)&lt;br /&gt;
            CheckImageButton(isChecked: $isChecked2)&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
struct CheckImageButton: View {&lt;br /&gt;
    @Binding var isChecked: Bool&lt;br /&gt;
    var body: some View {&lt;br /&gt;
        Button(action: {&lt;br /&gt;
            self.isChecked.toggle()&lt;br /&gt;
        }) {&lt;br /&gt;
            Image(systemName: isChecked ?&lt;br /&gt;
                &amp;quot;person.crop.circle.badge.checkmark&amp;quot;:&lt;br /&gt;
                &amp;quot;person.crop.circle&amp;quot;)&lt;br /&gt;
                .foregroundColor(&lt;br /&gt;
                    isChecked ? .blue : .gray)&lt;br /&gt;
        }&lt;br /&gt;
        .imageScale(.large)&lt;br /&gt;
        .frame(width: 40)&lt;br /&gt;
    &lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
====リストのBinding====&lt;br /&gt;
----&lt;br /&gt;
[[File:swiftui_binding_list.png|500px]]&lt;br /&gt;
&lt;br /&gt;
*Model&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import Foundation&lt;br /&gt;
import AppKit&lt;br /&gt;
import SwiftUI&lt;br /&gt;
&lt;br /&gt;
class File : Identifiable, ObservableObject {&lt;br /&gt;
    let id = UUID()&lt;br /&gt;
    let path: String&lt;br /&gt;
    let name: String&lt;br /&gt;
    let isDirectory: Bool&lt;br /&gt;
    var isOn: Bool = false&lt;br /&gt;
    &lt;br /&gt;
    init(path: String, name: String, isDirectory: Bool, isOn: Bool) {&lt;br /&gt;
        self.path = path&lt;br /&gt;
        self.name = name&lt;br /&gt;
        self.isDirectory = isDirectory&lt;br /&gt;
        self.isOn = isOn&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
class FileList : ObservableObject {&lt;br /&gt;
    @Published var files: [File] = []&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
*UI&lt;br /&gt;
**各所(①②③)に$をつける&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import SwiftUI&lt;br /&gt;
&lt;br /&gt;
struct ContentView: View {&lt;br /&gt;
    @ObservedObject var filePaths = FileList()&lt;br /&gt;
    @State private var selectedPaths = Set&amp;lt;File.ID&amp;gt;()&lt;br /&gt;
    &lt;br /&gt;
    var body: some View {&lt;br /&gt;
        Button(action: {&lt;br /&gt;
            let rootDir = EncConverterService.chooseDir()&lt;br /&gt;
            let queue = DispatchQueue.global(qos: .userInitiated)&lt;br /&gt;
            queue.async {&lt;br /&gt;
                EncConverterService.loadFile(directoryPath: rootDir, filepaths: self.filePaths)&lt;br /&gt;
            }&lt;br /&gt;
        }) {&lt;br /&gt;
            Text(&amp;quot;Choose dir&amp;quot;)  &lt;br /&gt;
        }&lt;br /&gt;
        &lt;br /&gt;
        Table($filePaths.files, selection: $selectedPaths) {   // ①&lt;br /&gt;
            TableColumn(&amp;quot;path&amp;quot;) { $file in  // ②&lt;br /&gt;
                let isDir = file.isDirectory&lt;br /&gt;
                HStack {&lt;br /&gt;
                    if !isDir {&lt;br /&gt;
                        Toggle(&amp;quot;&amp;quot;,isOn: $file.isOn) //　③&lt;br /&gt;
                            .padding(.leading, (isDir) ? 0 : 20)&lt;br /&gt;
                    }&lt;br /&gt;
                    Text((isDir) ? file.path : file.name)&lt;br /&gt;
                        .font((isDir) ? .headline : .none)&lt;br /&gt;
                        &lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
        Text(&amp;quot;\(selectedPaths.count) path selected&amp;quot;)&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===画像===&lt;br /&gt;
----&lt;br /&gt;
[[File:Swiftui image sample.png|600px]]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import SwiftUI&lt;br /&gt;
&lt;br /&gt;
struct ContentView: View {&lt;br /&gt;
    var body: some View {&lt;br /&gt;
        VStack {&lt;br /&gt;
            Image(&amp;quot;add_component_swiftui&amp;quot;).resizable()&lt;br /&gt;
                .aspectRatio(contentMode:.fill)&lt;br /&gt;
                .frame(width: 400, height: 400)&lt;br /&gt;
                .scaleEffect(1.2)&lt;br /&gt;
                .offset(x: -60, y: 0)&lt;br /&gt;
                .clipped()&lt;br /&gt;
                .overlay(&lt;br /&gt;
                    Text(&amp;quot;SwiftUI Sample&amp;quot;)&lt;br /&gt;
                        .font(.title)&lt;br /&gt;
                        .foregroundColor(.red)&lt;br /&gt;
                )&lt;br /&gt;
                .clipShape(Circle()/)&lt;br /&gt;
                .shadow(radius: 10)&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
struct ContentView_Previews: PreviewProvider {&lt;br /&gt;
    static var previews: some View {&lt;br /&gt;
        ContentView()&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===図形===&lt;br /&gt;
----&lt;br /&gt;
[[File:Swiftui_sample_figure.png|600px]]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import SwiftUI&lt;br /&gt;
&lt;br /&gt;
struct Figure: View {&lt;br /&gt;
    var body: some View {&lt;br /&gt;
          VStack {&lt;br /&gt;
              Circle()&lt;br /&gt;
                  .foregroundColor(.blue)&lt;br /&gt;
                  .frame(width: 100.0, height:100.0)&lt;br /&gt;
              Ellipse()&lt;br /&gt;
                  .foregroundColor(.green)&lt;br /&gt;
                  .frame(width: 200, height: 100.0)&lt;br /&gt;
              Rectangle()&lt;br /&gt;
                  .foregroundColor(.orange)&lt;br /&gt;
                  .frame(width: 100.0, height: 100.0)&lt;br /&gt;
                  .rotationEffect(.degrees(45))&lt;br /&gt;
            }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
struct Figure_Previews: PreviewProvider {&lt;br /&gt;
    static var previews: some View {&lt;br /&gt;
        Figure()&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===List===&lt;br /&gt;
----&lt;br /&gt;
[[File:Swiftui_list_sample.png|600px]]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import SwiftUI&lt;br /&gt;
&lt;br /&gt;
struct ListView: View {&lt;br /&gt;
    var body: some View {&lt;br /&gt;
        NavigationView {&lt;br /&gt;
            List {&lt;br /&gt;
                Text(&amp;quot;List Item&amp;quot;)&lt;br /&gt;
                Text(&amp;quot;List Item&amp;quot;)&lt;br /&gt;
                HStack {&lt;br /&gt;
                    Image(&amp;quot;add_component_swiftui&amp;quot;)&lt;br /&gt;
                        .frame(width: 100, height: 100)&lt;br /&gt;
                        .scaleEffect(0.2)&lt;br /&gt;
                        .aspectRatio(contentMode:.fit)&lt;br /&gt;
                        .clipped()&lt;br /&gt;
                        .clipShape(/*@START_MENU_TOKEN@*/Circle()/*@END_MENU_TOKEN@*/)&lt;br /&gt;
                       &lt;br /&gt;
                }&lt;br /&gt;
                Text(&amp;quot;List Item&amp;quot;)&lt;br /&gt;
                Text(&amp;quot;List Item&amp;quot;)&lt;br /&gt;
            }.navigationBarTitle(&amp;quot;List Title&amp;quot;)&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
struct ListView_Previews: PreviewProvider {&lt;br /&gt;
    static var previews: some View {&lt;br /&gt;
        ListView()&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====List(繰り返し、Section)====&lt;br /&gt;
----&lt;br /&gt;
[[File:Swiftui_list_section.png|600px]]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import SwiftUI&lt;br /&gt;
&lt;br /&gt;
let items = [&amp;quot;item1&amp;quot;,&amp;quot;item2&amp;quot;,&amp;quot;item3&amp;quot;,&amp;quot;item4&amp;quot;,&amp;quot;item5&amp;quot;];&lt;br /&gt;
struct EmbededList: View {&lt;br /&gt;
    var body: some View {&lt;br /&gt;
        VStack {&lt;br /&gt;
            List(0..&amp;lt;items.count) { idx in&lt;br /&gt;
                Text(items[idx])&lt;br /&gt;
            }&lt;br /&gt;
            .frame(height: 300.0)&lt;br /&gt;
            List {&lt;br /&gt;
                Section(header: Text(&amp;quot;Section1&amp;quot;)) {&lt;br /&gt;
                    ForEach(0 ..&amp;lt; items.count) { idx in&lt;br /&gt;
                        Text(items[idx])&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
                Section(header: Text(&amp;quot;Section2&amp;quot;)) {&lt;br /&gt;
                    ForEach(0 ..&amp;lt; items.count) { idx in&lt;br /&gt;
                        Text(items[idx])&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
struct EmbededList_Previews: PreviewProvider {&lt;br /&gt;
    static var previews: some View {&lt;br /&gt;
        EmbededList()&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Listにオブジェクトを表示====&lt;br /&gt;
----&lt;br /&gt;
[[File:swift_ui_object_load_to_list.png|500px]]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import SwiftUI&lt;br /&gt;
&lt;br /&gt;
struct ContentView: View {&lt;br /&gt;
    @ObservedObject var hosts = HostList()&lt;br /&gt;
    var body: some View {&lt;br /&gt;
        VStack {&lt;br /&gt;
            HStack {&lt;br /&gt;
                Button(action: {&lt;br /&gt;
                    WoLService().arp(hosts:self.hosts)&lt;br /&gt;
                }) {&lt;br /&gt;
                    Text(&amp;quot;arp -a&amp;quot;)&lt;br /&gt;
                }.padding()&lt;br /&gt;
            }&lt;br /&gt;
            Divider()&lt;br /&gt;
            List (hosts.hosts, id: \.ip){ host in&lt;br /&gt;
                Text(host.host)&lt;br /&gt;
                Text(host.ip)&lt;br /&gt;
                Text(host.macaddr)&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
*&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import Foundation&lt;br /&gt;
&lt;br /&gt;
class HostList : ObservableObject {&lt;br /&gt;
    @Published var hosts: [Host] = []&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
class Host {&lt;br /&gt;
    var host: String = &amp;quot;&amp;quot;&lt;br /&gt;
    var ip: String = &amp;quot;&amp;quot;&lt;br /&gt;
    var macaddr: String = &amp;quot;&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
===Table===&lt;br /&gt;
----&lt;br /&gt;
*https://developer.apple.com/documentation/swiftui/table&lt;br /&gt;
&lt;br /&gt;
[[File:swiftui_tableview.png|500px]]&lt;br /&gt;
&lt;br /&gt;
*Service&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import Foundation&lt;br /&gt;
import AppKit&lt;br /&gt;
import SwiftUI&lt;br /&gt;
&lt;br /&gt;
class File : Identifiable {&lt;br /&gt;
    let id = UUID()&lt;br /&gt;
    let path: String&lt;br /&gt;
    &lt;br /&gt;
    init(path: String) {&lt;br /&gt;
        self.path = path&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
class FileList : ObservableObject {&lt;br /&gt;
    @Published var files: [File] = []&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
public struct EncConverterService {&lt;br /&gt;
    static func chooseDir() -&amp;gt; String {&lt;br /&gt;
        &lt;br /&gt;
        let dialog = NSOpenPanel();&lt;br /&gt;
&lt;br /&gt;
        dialog.title                   = &amp;quot;Choose a file| Our Code World&amp;quot;&lt;br /&gt;
        dialog.showsResizeIndicator    = true&lt;br /&gt;
        dialog.showsHiddenFiles        = false&lt;br /&gt;
        dialog.allowsMultipleSelection = false&lt;br /&gt;
        dialog.canChooseDirectories    = true&lt;br /&gt;
        dialog.canChooseFiles          = false&lt;br /&gt;
&lt;br /&gt;
        if (dialog.runModal() ==  NSApplication.ModalResponse.OK) {&lt;br /&gt;
            let result = dialog.url&lt;br /&gt;
&lt;br /&gt;
            if (result != nil) {&lt;br /&gt;
                let path: String = result!.path&lt;br /&gt;
                return path&lt;br /&gt;
            }&lt;br /&gt;
            &lt;br /&gt;
        }&lt;br /&gt;
        return &amp;quot;&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    static func loadFile(directoryPath: String, filepaths: FileList) {&lt;br /&gt;
        print(directoryPath)&lt;br /&gt;
        filepaths.files.append(File(path: directoryPath))&lt;br /&gt;
        do {&lt;br /&gt;
            let fm = FileManager.default&lt;br /&gt;
            let fileNames = try fm.contentsOfDirectory(atPath: directoryPath)&lt;br /&gt;
            &lt;br /&gt;
            for fileName in fileNames {&lt;br /&gt;
                let childPath = directoryPath + &amp;quot;/&amp;quot; + fileName&lt;br /&gt;
                &lt;br /&gt;
                var isDir = ObjCBool(false)&lt;br /&gt;
                fm.fileExists(atPath: childPath, isDirectory: &amp;amp;isDir)&lt;br /&gt;
                if isDir.boolValue {&lt;br /&gt;
                    loadFile(directoryPath: childPath, filepaths: filepaths)&lt;br /&gt;
                }&lt;br /&gt;
                print(&amp;quot;\t&amp;quot; + childPath)&lt;br /&gt;
                filepaths.files.append(File(path: childPath))&lt;br /&gt;
            }&lt;br /&gt;
        } catch {&lt;br /&gt;
            print(error)&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
*View&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import SwiftUI&lt;br /&gt;
&lt;br /&gt;
struct ContentView: View {&lt;br /&gt;
    @ObservedObject var filePaths = FileList()&lt;br /&gt;
    @State private var selectedPaths = Set&amp;lt;File.ID&amp;gt;()&lt;br /&gt;
    &lt;br /&gt;
    var body: some View {&lt;br /&gt;
        Button(action: {&lt;br /&gt;
            let rootDir = EncConverterService.chooseDir()&lt;br /&gt;
            let queue = DispatchQueue.global(qos: .userInitiated)&lt;br /&gt;
            queue.async {&lt;br /&gt;
                EncConverterService.loadFile(directoryPath: rootDir, filepaths: self.filePaths)&lt;br /&gt;
            }&lt;br /&gt;
        }) {&lt;br /&gt;
            Text(&amp;quot;Choose dir&amp;quot;)&lt;br /&gt;
        }&lt;br /&gt;
        &lt;br /&gt;
        Table(filePaths.files, selection: $selectedPaths) {&lt;br /&gt;
            TableColumn(&amp;quot;Path&amp;quot;, value: \.path)&lt;br /&gt;
        }&lt;br /&gt;
        Text(&amp;quot;\(selectedPaths.count) path selected&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==コードサンプル(ロジック)==&lt;br /&gt;
&lt;br /&gt;
===Observable(@ObservedObject,@Published,@State)===&lt;br /&gt;
----&lt;br /&gt;
#データクラスはObservableObjectプロトコル準拠とする。&lt;br /&gt;
#監視対象とするプロパティに@Published属性を付加する。&lt;br /&gt;
#&amp;lt;u&amp;gt;データクラスのインスタンスは@ObservedObject属性を付加してViewの中で宣言する&amp;lt;/u&amp;gt;&lt;br /&gt;
[[File:swift_sample_observable.png|200px]]&lt;br /&gt;
*Publish&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import Foundation&lt;br /&gt;
&lt;br /&gt;
class PublishObject: ObservableObject {&lt;br /&gt;
    @Published var counter: Int = 0&lt;br /&gt;
    &lt;br /&gt;
    var timer = Timer()&lt;br /&gt;
    &lt;br /&gt;
    func start() {&lt;br /&gt;
        timer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { _ in&lt;br /&gt;
            self.counter += 1&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    func stop() {&lt;br /&gt;
        timer.invalidate()&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    func reset() {&lt;br /&gt;
        timer.invalidate()&lt;br /&gt;
        counter = 0&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
*Subscribe&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import SwiftUI&lt;br /&gt;
&lt;br /&gt;
struct SubscriberView: View {&lt;br /&gt;
    @ObservedObject var publisher = PublishObject()&lt;br /&gt;
    &lt;br /&gt;
    let currentTimer = Timer.TimerPublisher(interval: 1.0, runLoop: .main, mode: .default).autoconnect()&lt;br /&gt;
    @State var now = Date()&lt;br /&gt;
    &lt;br /&gt;
    var body: some View {&lt;br /&gt;
        VStack {&lt;br /&gt;
            Text(&amp;quot;\(self.now.description)&amp;quot;)&lt;br /&gt;
            HStack {&lt;br /&gt;
                Button(action: {&lt;br /&gt;
                    self.publisher.start()&lt;br /&gt;
                }){&lt;br /&gt;
                    Image(systemName: &amp;quot;play&amp;quot;)&lt;br /&gt;
                }.padding()&lt;br /&gt;
                Button(action: {&lt;br /&gt;
                    self.publisher.stop()&lt;br /&gt;
                }){&lt;br /&gt;
                    Image(systemName: &amp;quot;pause&amp;quot;)&lt;br /&gt;
                }.padding()&lt;br /&gt;
                Button(action: {&lt;br /&gt;
                    self.publisher.reset()&lt;br /&gt;
                }){&lt;br /&gt;
                    Image(systemName: &amp;quot;backward.end&amp;quot;)&lt;br /&gt;
                }.padding()&lt;br /&gt;
            }&lt;br /&gt;
            .frame(width:200)&lt;br /&gt;
        &lt;br /&gt;
            Text(&amp;quot;\(self.publisher.counter)&amp;quot;)&lt;br /&gt;
            &lt;br /&gt;
        }.font(.largeTitle)&lt;br /&gt;
        .onReceive(currentTimer) { date in&lt;br /&gt;
            self.now = date&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
===動的に検索===&lt;br /&gt;
[[File:swiftui_dynamic_search.png|400px]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
struct HostListView: View {&lt;br /&gt;
    @ObservedObject var hosts = HostList()&lt;br /&gt;
    @ObservedObject var param = HostViewParameter()&lt;br /&gt;
    // 検索キーワード&lt;br /&gt;
    @State var searchKeyword = &amp;quot;&amp;quot;&lt;br /&gt;
    &lt;br /&gt;
    var body: some View {&lt;br /&gt;
        VStack {&lt;br /&gt;
            let columns =&lt;br /&gt;
                [GridItem(.adaptive(minimum: 250, maximum: 800))]&lt;br /&gt;
            ScrollView {&lt;br /&gt;
                LazyVGrid(columns: columns, spacing:10) {&lt;br /&gt;
                    //　Arrayにfilterを適用&lt;br /&gt;
                    ForEach(hosts.hosts.filter({ (host) -&amp;gt; Bool in&lt;br /&gt;
                        if searchKeyword != &amp;quot;&amp;quot; {&lt;br /&gt;
                            return host.host.contains(searchKeyword) ||&lt;br /&gt;
                                host.ip.contains(searchKeyword) ||&lt;br /&gt;
                                host.comment.contains(searchKeyword)&lt;br /&gt;
                        }&lt;br /&gt;
                        return true&lt;br /&gt;
                    }), id: \.id) { host in&lt;br /&gt;
                        HostView(host:host).environmentObject(param)&lt;br /&gt;
                    }&lt;br /&gt;
                } .padding(20)&lt;br /&gt;
            }.toolbar {&lt;br /&gt;
                        :&lt;br /&gt;
               ToolbarItem(placement: .automatic) {&lt;br /&gt;
                    TextField(&amp;quot;search...&amp;quot;, text: $searchKeyword)&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===バックグラウンドからUIを操作する===&lt;br /&gt;
----&lt;br /&gt;
*observableobj が、ObservableObject の派生クラス&lt;br /&gt;
*contentフィールドに、@Published アノテーション&lt;br /&gt;
*Viewで、@ObservedObjectを付与しインスタンスを生成&lt;br /&gt;
*上記で、バックグラウンドから、observableobj.contentを操作すると、UIはメインスレッドから触るように怒られる。&lt;br /&gt;
&amp;lt;blockquote&amp;gt;Publishing changes from background threads is not allowed; make sure to publish values from the main thread (via operators like receive(on:)) on model updates.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
*DispatchQueue.main.syncで囲む&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
DispatchQueue.main.sync {&lt;br /&gt;
    observableobj.content = text&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Tips==&lt;br /&gt;
----&lt;br /&gt;
===VSCode + Github Copilot で iPhone アプリ開発===&lt;br /&gt;
*https://www.typea.info/blog/index.php/2024/12/29/vscode_and_github_copilot_dev_iphone_app/&lt;br /&gt;
===[https://www.typea.info/blog/index.php/2021/11/30/swift_macos_app_permission/ ファイルパーミッションエラー（App Sandbox)]===&lt;br /&gt;
----&lt;br /&gt;
*[https://www.typea.info/blog/index.php/2021/11/30/swift_macos_app_permission/ ファイルパーミッションエラー（App Sandbox)]&lt;br /&gt;
===[https://www.typea.info/blog/index.php/2021/01/23/swiftui_tips_view_component_locate/ 画面部品の追加方法]===&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===SwiftUIライブラリ===&lt;br /&gt;
----&lt;br /&gt;
====[https://github.com/SwiftUIX/SwiftUIX SwiftUIX]====&lt;br /&gt;
[https://qiita.com/yosshi4486/items/3d92f81feaabc1049b4c SwiftUIアプリケーション開発の不足を補うSwiftUIX]&lt;br /&gt;
&lt;br /&gt;
===ファイル選択===&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 let dialog = NSOpenPanel();&lt;br /&gt;
&lt;br /&gt;
dialog.title                   = &amp;quot;Choose a file&amp;quot;&lt;br /&gt;
dialog.showsResizeIndicator    = true&lt;br /&gt;
dialog.showsHiddenFiles        = false&lt;br /&gt;
dialog.allowsMultipleSelection = false&lt;br /&gt;
dialog.canChooseDirectories = false&lt;br /&gt;
&lt;br /&gt;
if (dialog.runModal() ==  NSApplication.ModalResponse.OK) {&lt;br /&gt;
	let result = dialog.url &lt;br /&gt;
	if (result != nil) {&lt;br /&gt;
		let path: String = result!.path&lt;br /&gt;
		print(path)&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
} else {&lt;br /&gt;
	return&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Piroto</name></author>
		
	</entry>
	<entry>
		<id>https://www.typea.info/tips_/index.php?title=Visual_Studio_Code&amp;diff=35365</id>
		<title>Visual Studio Code</title>
		<link rel="alternate" type="text/html" href="https://www.typea.info/tips_/index.php?title=Visual_Studio_Code&amp;diff=35365"/>
		<updated>2024-12-29T07:38:46Z</updated>

		<summary type="html">&lt;p&gt;Piroto: /* .NET Core */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;| [[Electron]] | [[Visual Studio]] |&lt;br /&gt;
==[[Visual Studio Code]]==&lt;br /&gt;
{{amazon|4297112019}}&lt;br /&gt;
&lt;br /&gt;
*[http://qiita.com/TakahiRoyte/items/cdab6fca64da386a690b 【Windows版】VS Code キーボードショートカット一覧]&lt;br /&gt;
*[http://qiita.com/aoinu/items/681f932ce0b162cd9520 Visual Studio Code チートシート]&lt;br /&gt;
*[http://sourcechord.hatenablog.com/entry/2015/05/06/230003 VisualStudio Codeの各種操作メモ]&lt;br /&gt;
*https://code.[[vi]]sualstudio.com/shortcuts/keyboard-shortcuts-windows.pdf&lt;br /&gt;
===キーボードショートカット===&lt;br /&gt;
[[Android Studio]]&lt;br /&gt;
&lt;br /&gt;
* 画面左下歯車アイコン -&amp;gt; キーボードショートカット で一覧表示される&lt;br /&gt;
====一般====&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!操作(Windows)&lt;br /&gt;
!操作(Mac)&lt;br /&gt;
!内容&lt;br /&gt;
|-&lt;br /&gt;
|Ctrl+Shift+P&lt;br /&gt;
|&lt;br /&gt;
|コマンドパレット&lt;br /&gt;
|-&lt;br /&gt;
|Ctrl+k s&lt;br /&gt;
|&lt;br /&gt;
|キーボードショートカット一覧&lt;br /&gt;
|-&lt;br /&gt;
|Ctrl+ , &lt;br /&gt;
|&lt;br /&gt;
|設定を開く&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
====表示====&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!操作(Windows)&lt;br /&gt;
!操作(Mac)&lt;br /&gt;
!内容&lt;br /&gt;
|-&lt;br /&gt;
|Ctrl+Q&lt;br /&gt;
|&lt;br /&gt;
|クイックオープンビュー&lt;br /&gt;
|-&lt;br /&gt;
|Ctrl+Shift+O&lt;br /&gt;
|&lt;br /&gt;
|メソッド一覧&lt;br /&gt;
|-&lt;br /&gt;
|Ctrl+B&lt;br /&gt;
|&lt;br /&gt;
|サイドバー(エクスプローラーなど)の開閉&lt;br /&gt;
|-&lt;br /&gt;
|Ctrl+Shift+E&lt;br /&gt;
|&lt;br /&gt;
|エクスプローラー&lt;br /&gt;
|-&lt;br /&gt;
|Ctrl+Shift+G&lt;br /&gt;
|&lt;br /&gt;
|ソースコード管理&lt;br /&gt;
|-&lt;br /&gt;
|Ctrl+\&lt;br /&gt;
|Ctrl+Cmd+Option+¥&lt;br /&gt;
|画面分割&lt;br /&gt;
|-&lt;br /&gt;
|Ctrl+Shift＋V&lt;br /&gt;
|Shft+Cmd+V&lt;br /&gt;
|[[Markdown]]をプレビュー&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
====編集====&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!操作(Windows)&lt;br /&gt;
!操作(Mac)&lt;br /&gt;
!内容&lt;br /&gt;
|-&lt;br /&gt;
|Alt+Click&lt;br /&gt;
|Option+Click&lt;br /&gt;
|[http://mugi1.hateblo.jp/entry/2018/12/11/215808 マルチカーソルを追加する]&lt;br /&gt;
|-&lt;br /&gt;
|Ctrl+Shift+Alt+矢印&lt;br /&gt;
|Shift+Option+Command+矢印&lt;br /&gt;
|矩形選択(キーボード)&lt;br /&gt;
|-&lt;br /&gt;
|Shift+Alt+ドラッグ&lt;br /&gt;
|Shift+Option+ドラッグ&lt;br /&gt;
|矩形選択(マウス) 始点クリック→終点クリック&lt;br /&gt;
|-&lt;br /&gt;
|Ctrl+Shift+L&lt;br /&gt;
|Command+Shift+L&lt;br /&gt;
|選択部分の全マッチを選択&lt;br /&gt;
|-&lt;br /&gt;
|Ctrl+K Ctrl+D&lt;br /&gt;
|&lt;br /&gt;
|次のマッチに移動&lt;br /&gt;
|-&lt;br /&gt;
|Ctrl+F2&lt;br /&gt;
|Command+F2&lt;br /&gt;
|すべての出現箇所を変更&lt;br /&gt;
|-&lt;br /&gt;
|Ctrl+.&lt;br /&gt;
|&lt;br /&gt;
|クイック修正(波下線が表示されているエラーなど)&lt;br /&gt;
|-&lt;br /&gt;
|Alt+↑/↓&lt;br /&gt;
|&lt;br /&gt;
|行の移動&lt;br /&gt;
|-&lt;br /&gt;
|Shift+Alt+↑/↓&lt;br /&gt;
|Shift+Option+↑/↓&lt;br /&gt;
|行のコピー&lt;br /&gt;
|-&lt;br /&gt;
|Ctrl+Shift+k&lt;br /&gt;
|Command+Shift+K&lt;br /&gt;
|行の削除&lt;br /&gt;
|-&lt;br /&gt;
|Ctrl+j&lt;br /&gt;
|Command+j&lt;br /&gt;
|行のマージ&lt;br /&gt;
|-&lt;br /&gt;
|Ctrl+Shift+P -&amp;gt; Sort Lines Ascending&lt;br /&gt;
|Command+Shift+P -&amp;gt; Sort Lines Ascending&lt;br /&gt;
|行の昇順並べ替え&lt;br /&gt;
|-&lt;br /&gt;
|Ctrl+k, Ctrl+f&lt;br /&gt;
|Command+k, Command+f&lt;br /&gt;
|コードフォーマット、書式整形&lt;br /&gt;
|-&lt;br /&gt;
|Ctrl + Space&lt;br /&gt;
|Command+Space &lt;br /&gt;
※ Spotlight無効化　システム環境設定 - キーボード-ショートカット - Spotlight - Spotlight検索を表示のチェックを外す&lt;br /&gt;
|コード補完&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
====検索と置換====&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!操作(Windows)&lt;br /&gt;
!操作(Mac)&lt;br /&gt;
!内容&lt;br /&gt;
|-&lt;br /&gt;
|Ctrl+K Ctrl+S&lt;br /&gt;
|&lt;br /&gt;
|キーボードショートカット一覧を表示&lt;br /&gt;
|-&lt;br /&gt;
|Ctrl+p&lt;br /&gt;
|Command+p&lt;br /&gt;
|ファイル名を検索&lt;br /&gt;
|-&lt;br /&gt;
|Ctrl+Shift+O&lt;br /&gt;
|Command+Shift+O&lt;br /&gt;
|シンボルを検索（メソッドなど)&lt;br /&gt;
|-&lt;br /&gt;
|Ctrl+P&lt;br /&gt;
|&lt;br /&gt;
|ファイルを検索して開く&lt;br /&gt;
|-&lt;br /&gt;
|Ctrl+T&lt;br /&gt;
|&lt;br /&gt;
|全ファイルにまたがって参照検索して移動し、ファイルを開く&lt;br /&gt;
|-&lt;br /&gt;
|Ctrl+Shift+F&lt;br /&gt;
|&lt;br /&gt;
|全ファイルから検索&lt;br /&gt;
|-&lt;br /&gt;
|Ctrl+Shift+J&lt;br /&gt;
|&lt;br /&gt;
|検索詳細設定&lt;br /&gt;
|-&lt;br /&gt;
|Alt+C&lt;br /&gt;
|&lt;br /&gt;
|大文字小文字区別の切り替え&lt;br /&gt;
|-&lt;br /&gt;
|Alt+R&lt;br /&gt;
|&lt;br /&gt;
|[[正規表現]]要否の切り替え&lt;br /&gt;
|-&lt;br /&gt;
|Alt+W&lt;br /&gt;
|&lt;br /&gt;
|ワード選択の切り替え&lt;br /&gt;
|-&lt;br /&gt;
|Alt+Enter&lt;br /&gt;
|&lt;br /&gt;
|マッチ個所の全選択&lt;br /&gt;
|-&lt;br /&gt;
|Ctrl+G&lt;br /&gt;
|Ctrl+G&lt;br /&gt;
|指定行へジャンプ&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===設定===&lt;br /&gt;
====Workspace====&lt;br /&gt;
*File - Preference - Settings - Workspaceタブ&lt;br /&gt;
&lt;br /&gt;
====MacでPATHを通す====&lt;br /&gt;
*以下を~/.bash_profile に追記&lt;br /&gt;
 export PATH=&amp;quot;/Applications/Visual Studio Code.app/Contents/Resources/app/bin:$PATH&amp;quot;&lt;br /&gt;
&lt;br /&gt;
==デバッグ==&lt;br /&gt;
*https://code.[[vi]]sualstudio.com/docs/editor/debugging#_launch-configurations&lt;br /&gt;
&lt;br /&gt;
==[[Java]]==&lt;br /&gt;
*[https://code.visualstudio.com/docs/java/java-tutorial VSCode Java]&lt;br /&gt;
===[https://code.visualstudio.com/docs/java/java-refactoring リファクタリング]===&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!操作&lt;br /&gt;
!内容&lt;br /&gt;
|-&lt;br /&gt;
|メソッドの実装とオーバーライド&lt;br /&gt;
|コンテキストメニュー - Source Action - Override/Imprement methods&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==[[.NET Core]]==&lt;br /&gt;
===C# および [[Visual Studio Code]] の使用を開始する===&lt;br /&gt;
*https://docs.microsoft.com/ja-jp/dotnet/core/tutorials/with-[[vi]]sual-studio-code&lt;br /&gt;
&lt;br /&gt;
====シンプルなプロジェクト====&lt;br /&gt;
=====プロジェクト作成=====&lt;br /&gt;
*https://docs.microsoft.com/ja-jp/dotnet/core/tools/dotnet-new?tabs=netcore21&lt;br /&gt;
 dotnet new console&lt;br /&gt;
=====ビルド=====&lt;br /&gt;
 dotnet build&lt;br /&gt;
=====実行=====&lt;br /&gt;
 dotnet run&lt;br /&gt;
&lt;br /&gt;
==[[SwiftUI]]==&lt;br /&gt;
===VSCode + Github Copilot で iPhone アプリ開発===&lt;br /&gt;
*https://www.typea.info/blog/index.php/2024/12/29/vscode_and_github_copilot_dev_iphone_app/&lt;br /&gt;
&lt;br /&gt;
==Extension==&lt;br /&gt;
===Remote SSH===&lt;br /&gt;
----&lt;br /&gt;
*リモートのワークスペースに接続&lt;br /&gt;
&lt;br /&gt;
[[File:vs_remote_ssh.png|600px]]&lt;br /&gt;
===Remote Containers===&lt;br /&gt;
----&lt;br /&gt;
*https://techblog.roxx.co.jp/entry/2021/04/19/132838&lt;br /&gt;
[[File:vscode_extension_remote_container.png|600px]]&lt;br /&gt;
&lt;br /&gt;
===Rest Client===&lt;br /&gt;
----&lt;br /&gt;
*https://marketplace.visualstudio.com/items?itemName=humao.rest-client&lt;br /&gt;
[[File:vscode_restclient.png|600px]]&lt;br /&gt;
*cmd + option + r で送信&lt;br /&gt;
*複数を区切る時には、###&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
GET https://example.com/comments/1 HTTP/1.1&lt;br /&gt;
&lt;br /&gt;
###&lt;br /&gt;
&lt;br /&gt;
GET https://example.com/topics/1 HTTP/1.1&lt;br /&gt;
&lt;br /&gt;
###&lt;br /&gt;
&lt;br /&gt;
POST https://example.com/comments HTTP/1.1&lt;br /&gt;
content-type: application/json&lt;br /&gt;
&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;sample&amp;quot;,&lt;br /&gt;
    &amp;quot;time&amp;quot;: &amp;quot;Wed, 21 Oct 2015 18:27:50 GMT&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===[[PlantUML]]===&lt;br /&gt;
====[[Mac]]====&lt;br /&gt;
*[[Java SE|Java]]のインストール&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ brew install graphviz&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:plantuml_vc.png | 600px]]&lt;br /&gt;
*tcp.pu&lt;br /&gt;
*option + d でプレビュー&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
@startuml&lt;br /&gt;
title TCP コネクション確立&lt;br /&gt;
クライアント -&amp;gt; サーバ: 1.SYN&lt;br /&gt;
サーバ --&amp;gt; クライアント: 2.SYN/ACk&lt;br /&gt;
クライアント -&amp;gt; サーバ: 1.ACK&lt;br /&gt;
@enduml&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
[[File:plantuml_tcp.png | 800px]]&lt;br /&gt;
&lt;br /&gt;
==[[Tips]]==&lt;br /&gt;
===[[文字コード]]自動判別===&lt;br /&gt;
 &amp;quot;files.autoGuessEncoding&amp;quot;: true&lt;br /&gt;
&lt;br /&gt;
[[category:VisualStudio操作]]&lt;/div&gt;</summary>
		<author><name>Piroto</name></author>
		
	</entry>
	<entry>
		<id>https://www.typea.info/tips_/index.php?title=MarsEdit&amp;diff=35364</id>
		<title>MarsEdit</title>
		<link rel="alternate" type="text/html" href="https://www.typea.info/tips_/index.php?title=MarsEdit&amp;diff=35364"/>
		<updated>2024-12-02T16:05:26Z</updated>

		<summary type="html">&lt;p&gt;Piroto: ページの作成:「=MarsEdit=   ==キーボードショートカット== * HTMLエディタ切り替え：Command+Shift+t」&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=MarsEdit=&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==キーボードショートカット==&lt;br /&gt;
* HTMLエディタ切り替え：Command+Shift+t&lt;/div&gt;</summary>
		<author><name>Piroto</name></author>
		
	</entry>
	<entry>
		<id>https://www.typea.info/tips_/index.php?title=AWS&amp;diff=35363</id>
		<title>AWS</title>
		<link rel="alternate" type="text/html" href="https://www.typea.info/tips_/index.php?title=AWS&amp;diff=35363"/>
		<updated>2024-10-28T10:43:56Z</updated>

		<summary type="html">&lt;p&gt;Piroto: /* AWS Organizations */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==AWS==&lt;br /&gt;
===[https://wa.aws.amazon.com/wellarchitected/2020-07-02T19-33-23/index.ja.html AWS Well-Architectedプレームワーク]===&lt;br /&gt;
&lt;br /&gt;
*AWS Well-Architectedプレームワークと呼ばれる、クラウド活用のベストプラクティスをまとめたホワイトペーパーが無償提供されている&lt;br /&gt;
&lt;br /&gt;
* 五つの柱&lt;br /&gt;
# 運用上の優秀性&lt;br /&gt;
# セキュリティ&lt;br /&gt;
# 信頼性&lt;br /&gt;
# パフォーマンス効率&lt;br /&gt;
# コスト最適化&lt;br /&gt;
===AWSインフラストラクチャ===&lt;br /&gt;
====リージョンとアベイラビリティゾーン====&lt;br /&gt;
*リージョンは地理的に離れた領域、アベイラビリティゾーンはリージョン内にある複数のデータセンターの集合体&lt;br /&gt;
*各AZ間は、冗長化された高速なネットワークで接続されており、それぞれ地理・電源・ネットワークが独立した施設で構成&lt;br /&gt;
*高可用性の実現のためにマルチAZ構成が推奨されている&lt;br /&gt;
*災害対策サイトの場合、マルチリージョン構成とすることもある&lt;br /&gt;
====エッジロケーション====&lt;br /&gt;
*Amazon CloudFronのコンテンツやAmazon Route 53のDNSサービスを提供するデータセンター&lt;br /&gt;
*世界中でAZを上回る拠点を構え、ユーザーは地理的に近いエッジロケーションから配布されるコンテンツを利用できる&lt;br /&gt;
====AWSサービス範囲====&lt;br /&gt;
* グローバルサービス&lt;br /&gt;
** リージョンに依存しない共通サービス：IAM、CloudFront、Route53など&lt;br /&gt;
* リージョンサービス&lt;br /&gt;
** 特定リージョン内でのみ利用可能：VPC、DynamoDB、Lambdaなど&lt;br /&gt;
* アベイラビリティゾーンサービス&lt;br /&gt;
**特定のAZ内で利用するサービス：VPCサブネット、EC2、RDSなど&lt;br /&gt;
==AWS Organizations==&lt;br /&gt;
&lt;br /&gt;
*複数のアカウントを管理できる&lt;br /&gt;
*OUという組織単位を作成し個々のアカウントを紐づけて管理&lt;br /&gt;
*組織単位でポリシーを一元管理&lt;br /&gt;
*Organizations APIによるアカウント作成の自動化&lt;br /&gt;
**複数ユーザーの一括作成&lt;br /&gt;
*SCP(Service Control Policy)&lt;br /&gt;
**所属アカウントを一元管理&lt;br /&gt;
*継承される&lt;br /&gt;
*一括請求管理機能(組織単位の請求)&lt;br /&gt;
**無料利用枠、割引の組織内共有&lt;br /&gt;
*他サービスと連携して利用される。&lt;br /&gt;
**AWS CloudFormation:共同開発が可能になる&lt;br /&gt;
**AWS CloudTrail:組織単位でアカウントの証跡をとる&lt;br /&gt;
**AWS Control Tower:ランディングゾーン(初期設定テンプレート)の構成、複数アカウント環境を自動設定&lt;/div&gt;</summary>
		<author><name>Piroto</name></author>
		
	</entry>
	<entry>
		<id>https://www.typea.info/tips_/index.php?title=AWS&amp;diff=35362</id>
		<title>AWS</title>
		<link rel="alternate" type="text/html" href="https://www.typea.info/tips_/index.php?title=AWS&amp;diff=35362"/>
		<updated>2024-10-28T10:38:29Z</updated>

		<summary type="html">&lt;p&gt;Piroto: /* AWS Organizations */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==AWS==&lt;br /&gt;
===[https://wa.aws.amazon.com/wellarchitected/2020-07-02T19-33-23/index.ja.html AWS Well-Architectedプレームワーク]===&lt;br /&gt;
&lt;br /&gt;
*AWS Well-Architectedプレームワークと呼ばれる、クラウド活用のベストプラクティスをまとめたホワイトペーパーが無償提供されている&lt;br /&gt;
&lt;br /&gt;
* 五つの柱&lt;br /&gt;
# 運用上の優秀性&lt;br /&gt;
# セキュリティ&lt;br /&gt;
# 信頼性&lt;br /&gt;
# パフォーマンス効率&lt;br /&gt;
# コスト最適化&lt;br /&gt;
===AWSインフラストラクチャ===&lt;br /&gt;
====リージョンとアベイラビリティゾーン====&lt;br /&gt;
*リージョンは地理的に離れた領域、アベイラビリティゾーンはリージョン内にある複数のデータセンターの集合体&lt;br /&gt;
*各AZ間は、冗長化された高速なネットワークで接続されており、それぞれ地理・電源・ネットワークが独立した施設で構成&lt;br /&gt;
*高可用性の実現のためにマルチAZ構成が推奨されている&lt;br /&gt;
*災害対策サイトの場合、マルチリージョン構成とすることもある&lt;br /&gt;
====エッジロケーション====&lt;br /&gt;
*Amazon CloudFronのコンテンツやAmazon Route 53のDNSサービスを提供するデータセンター&lt;br /&gt;
*世界中でAZを上回る拠点を構え、ユーザーは地理的に近いエッジロケーションから配布されるコンテンツを利用できる&lt;br /&gt;
====AWSサービス範囲====&lt;br /&gt;
* グローバルサービス&lt;br /&gt;
** リージョンに依存しない共通サービス：IAM、CloudFront、Route53など&lt;br /&gt;
* リージョンサービス&lt;br /&gt;
** 特定リージョン内でのみ利用可能：VPC、DynamoDB、Lambdaなど&lt;br /&gt;
* アベイラビリティゾーンサービス&lt;br /&gt;
**特定のAZ内で利用するサービス：VPCサブネット、EC2、RDSなど&lt;br /&gt;
==AWS Organizations==&lt;br /&gt;
&lt;br /&gt;
*複数のアカウントを管理できる&lt;br /&gt;
*OUという組織単位を作成し個々のアカウントを紐づけて管理&lt;br /&gt;
*組織単位でポリシーを一元管理&lt;br /&gt;
*Organizations APIによるアカウント作成の自動化&lt;br /&gt;
**複数ユーザーの一括作成&lt;br /&gt;
*SCP(Service Control Policy)&lt;br /&gt;
**所属アカウントを一元管理&lt;/div&gt;</summary>
		<author><name>Piroto</name></author>
		
	</entry>
	<entry>
		<id>https://www.typea.info/tips_/index.php?title=AWS&amp;diff=35361</id>
		<title>AWS</title>
		<link rel="alternate" type="text/html" href="https://www.typea.info/tips_/index.php?title=AWS&amp;diff=35361"/>
		<updated>2024-10-28T10:36:02Z</updated>

		<summary type="html">&lt;p&gt;Piroto: /* AWSサービス範囲 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==AWS==&lt;br /&gt;
===[https://wa.aws.amazon.com/wellarchitected/2020-07-02T19-33-23/index.ja.html AWS Well-Architectedプレームワーク]===&lt;br /&gt;
&lt;br /&gt;
*AWS Well-Architectedプレームワークと呼ばれる、クラウド活用のベストプラクティスをまとめたホワイトペーパーが無償提供されている&lt;br /&gt;
&lt;br /&gt;
* 五つの柱&lt;br /&gt;
# 運用上の優秀性&lt;br /&gt;
# セキュリティ&lt;br /&gt;
# 信頼性&lt;br /&gt;
# パフォーマンス効率&lt;br /&gt;
# コスト最適化&lt;br /&gt;
===AWSインフラストラクチャ===&lt;br /&gt;
====リージョンとアベイラビリティゾーン====&lt;br /&gt;
*リージョンは地理的に離れた領域、アベイラビリティゾーンはリージョン内にある複数のデータセンターの集合体&lt;br /&gt;
*各AZ間は、冗長化された高速なネットワークで接続されており、それぞれ地理・電源・ネットワークが独立した施設で構成&lt;br /&gt;
*高可用性の実現のためにマルチAZ構成が推奨されている&lt;br /&gt;
*災害対策サイトの場合、マルチリージョン構成とすることもある&lt;br /&gt;
====エッジロケーション====&lt;br /&gt;
*Amazon CloudFronのコンテンツやAmazon Route 53のDNSサービスを提供するデータセンター&lt;br /&gt;
*世界中でAZを上回る拠点を構え、ユーザーは地理的に近いエッジロケーションから配布されるコンテンツを利用できる&lt;br /&gt;
====AWSサービス範囲====&lt;br /&gt;
* グローバルサービス&lt;br /&gt;
** リージョンに依存しない共通サービス：IAM、CloudFront、Route53など&lt;br /&gt;
* リージョンサービス&lt;br /&gt;
** 特定リージョン内でのみ利用可能：VPC、DynamoDB、Lambdaなど&lt;br /&gt;
* アベイラビリティゾーンサービス&lt;br /&gt;
**特定のAZ内で利用するサービス：VPCサブネット、EC2、RDSなど&lt;br /&gt;
==AWS Organizations==&lt;/div&gt;</summary>
		<author><name>Piroto</name></author>
		
	</entry>
	<entry>
		<id>https://www.typea.info/tips_/index.php?title=MediaWiki:Sidebar&amp;diff=35360</id>
		<title>MediaWiki:Sidebar</title>
		<link rel="alternate" type="text/html" href="https://www.typea.info/tips_/index.php?title=MediaWiki:Sidebar&amp;diff=35360"/>
		<updated>2024-10-28T10:34:51Z</updated>

		<summary type="html">&lt;p&gt;Piroto: /* MyMemoWiki */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==MyMemoWiki==&lt;br /&gt;
* navigation&lt;br /&gt;
** mainpage|mainpage-description&lt;br /&gt;
** recentchanges-url|recentchanges&lt;br /&gt;
** randompage-url|randompage&lt;br /&gt;
** helppage|help-mediawiki&lt;br /&gt;
* SEARCH&lt;br /&gt;
* TOOLBOX&lt;br /&gt;
* LANGUAGES&lt;br /&gt;
&lt;br /&gt;
* navigation&lt;br /&gt;
**特別:Categories|カテゴリ&lt;br /&gt;
*プログラミング 言語&lt;br /&gt;
** 言語 まとめ|まとめ&lt;br /&gt;
** ActionScript|ActionScript&lt;br /&gt;
** Programming C|C&lt;br /&gt;
** C Sharp|C#&lt;br /&gt;
** C++|C++&lt;br /&gt;
** COBOL|COBOL&lt;br /&gt;
** Dart|Dart&lt;br /&gt;
** Electron|Electron&lt;br /&gt;
** Flutter|Flutter&lt;br /&gt;
** Windows|Windows&lt;br /&gt;
** ASP.NET|ASP.NET&lt;br /&gt;
** ASP.NET Core|ASP.NET Core&lt;br /&gt;
** C#|C#&lt;br /&gt;
** Silverlight|Silverlight&lt;br /&gt;
**VC++ .NET|VC++ .NET&lt;br /&gt;
** WPF|WPF&lt;br /&gt;
** Universal Windows Platform|Universal Windows Platform&lt;br /&gt;
** .NET Core|.NET Core&lt;br /&gt;
** Xamarin|Xamarin&lt;br /&gt;
** Groovy|Groovy&lt;br /&gt;
** Java|Java&lt;br /&gt;
** Java SE|Java SE&lt;br /&gt;
** Java EE|Java EE&lt;br /&gt;
** Spring Boot|Spring Boot&lt;br /&gt;
** Eclipse|Eclipse&lt;br /&gt;
** JavaScript|JavaScript&lt;br /&gt;
** jQuery|jQuery&lt;br /&gt;
** Angular|Angular&lt;br /&gt;
** AngularJS|AngularJS&lt;br /&gt;
** React|React&lt;br /&gt;
** Next.js|Next.js&lt;br /&gt;
** Vue|Vue&lt;br /&gt;
** Jython|Jython&lt;br /&gt;
** Kotlin|Kotlin&lt;br /&gt;
** Lisp|Lisp&lt;br /&gt;
** Objective-C|Objective-C&lt;br /&gt;
** PL／I|PL／I&lt;br /&gt;
** Perl|Perl&lt;br /&gt;
** PHP|PHP&lt;br /&gt;
** Python|Python&lt;br /&gt;
** 言語まとめ Python|まとめ&lt;br /&gt;
** Python 標準ライブラリ概観|標準ライブラリ&lt;br /&gt;
** Python ライブラリ|ライブラリ&lt;br /&gt;
** Django|Django&lt;br /&gt;
** Flask|Flask&lt;br /&gt;
** Python3|Python3&lt;br /&gt;
** Powershell|Powershell&lt;br /&gt;
** R|R&lt;br /&gt;
** Racket|Racket&lt;br /&gt;
** Ruby|Ruby&lt;br /&gt;
** Scala|Scala&lt;br /&gt;
** SQL|SQL&lt;br /&gt;
** Scheme|Scheme&lt;br /&gt;
** Swift|Swift&lt;br /&gt;
** SwiftUI|SwiftUI&lt;br /&gt;
** TypeScript|TypeScript&lt;br /&gt;
** UML|UML&lt;br /&gt;
** VB6|VB6&lt;br /&gt;
** VBA|VBA&lt;br /&gt;
** VBScript|VBScript&lt;br /&gt;
**VC++|VC++&lt;br /&gt;
**VC++ .NET|VC++ .NET&lt;br /&gt;
** WScript|WScript&lt;br /&gt;
** XML|XML&lt;br /&gt;
** 正規表現|正規表現&lt;br /&gt;
** スクリプト(Win)|コマンド|スクリプト(Win)|コマンド&lt;br /&gt;
** シェルプログラミング|スクリプト(シェル)&lt;br /&gt;
*Web&lt;br /&gt;
** Apache|Apache&lt;br /&gt;
** IHS|IHS&lt;br /&gt;
** WAS|WAS&lt;br /&gt;
** GlassFish|GlassFish&lt;br /&gt;
** JBoss|JBoss&lt;br /&gt;
** WildFly|WildFly&lt;br /&gt;
** Node.js|Node.js&lt;br /&gt;
** CSS|CSS&lt;br /&gt;
** CSS3|CSS3&lt;br /&gt;
** Bootstrap|Bootstrap&lt;br /&gt;
** HTML|HTML&lt;br /&gt;
** HTTP|HTTP&lt;br /&gt;
** Markdown|Markdown&lt;br /&gt;
*OS/環境&lt;br /&gt;
** Android|Android&lt;br /&gt;
** Linux|Linux&lt;br /&gt;
** LPIC| Linux LPIC&lt;br /&gt;
** CentOS|CentOS&lt;br /&gt;
** CentOS7|CentOS7&lt;br /&gt;
** Fedora|Fedora&lt;br /&gt;
** Ubuntu|Ubuntu&lt;br /&gt;
** Mint|Mint&lt;br /&gt;
** Mac|Mac&lt;br /&gt;
** UNIX|UNIX&lt;br /&gt;
** Windows|Windows&lt;br /&gt;
** Windows Mobile|Windows Mobile&lt;br /&gt;
** Windows Phone|Windows Phone&lt;br /&gt;
** iOS|iOS&lt;br /&gt;
** Kindle|Kindle&lt;br /&gt;
** Hinemos|Hinemos&lt;br /&gt;
** Raspberry Pi|Raspberry Pi&lt;br /&gt;
* データベース&lt;br /&gt;
** Database|全般&lt;br /&gt;
** IDEF1X|IDEF1X&lt;br /&gt;
** ER図|ER図&lt;br /&gt;
** DFD|DFD&lt;br /&gt;
** SQL|SQL&lt;br /&gt;
* Database|データベース製品&lt;br /&gt;
** Access|Access&lt;br /&gt;
** Apache Derby|Apache Derby&lt;br /&gt;
** DB2|DB2&lt;br /&gt;
** MySQL|MySQL&lt;br /&gt;
** Oracle|Oracle&lt;br /&gt;
** PostgreSQL|PostgreSQL&lt;br /&gt;
** SQL Server|SQL Server&lt;br /&gt;
** sqlite|sqlite&lt;br /&gt;
** MongoDB|MongoDB&lt;br /&gt;
*アーキテクチャ・モデリング・パターン&lt;br /&gt;
** DFD|DFD&lt;br /&gt;
** ER図|ER図&lt;br /&gt;
** J2EEパターン|J2EEパターン&lt;br /&gt;
** UML|UML&lt;br /&gt;
** アルゴリズム|アルゴリズム&lt;br /&gt;
** GOF デザインパターン|デザインパターン|GOF デザインパターン|デザインパターン&lt;br /&gt;
** リファクタリング|リファクタリング&lt;br /&gt;
** レスポンシブWebデザイン|レスポンシブWebデザイン&lt;br /&gt;
** Clean Architecture|Clean Architecture&lt;br /&gt;
*&lt;br /&gt;
*環境&lt;br /&gt;
** Android Studio|Android Studio&lt;br /&gt;
** Cygwin|Cygwin&lt;br /&gt;
** Eclipse|Eclipse&lt;br /&gt;
** IE|IE&lt;br /&gt;
** Visual Studio|Visual Studio&lt;br /&gt;
** Visual Studio Code|Visual Studio Code&lt;br /&gt;
** vi|vi&lt;br /&gt;
** Windows Live Writer|Windows Live Writer&lt;br /&gt;
** Maven|Maven&lt;br /&gt;
** YEOMAN|YEOMAN&lt;br /&gt;
** Bower|Bower&lt;br /&gt;
** Gradle|Gradle&lt;br /&gt;
** Unity|Unity&lt;br /&gt;
** Xcode|Xcode&lt;br /&gt;
* Webサービス&lt;br /&gt;
** Amazon Web Service|Amazon Web Service&lt;br /&gt;
** AWS|AWS&lt;br /&gt;
** Firebase|Firebase&lt;br /&gt;
** Google App Engine|Google App Engine&lt;br /&gt;
** Google App Engine(Java)|Google App Engine(Java)&lt;br /&gt;
** Google App Engine(.NET)|Google App Engine(.NET)&lt;br /&gt;
** Google Cloud Platform|Google Cloud Platform&lt;br /&gt;
** Twitter|Twitter&lt;br /&gt;
** mixi アプリ|mixi アプリ&lt;br /&gt;
* プロジェクトマネージメント&lt;br /&gt;
** プロジェクトマネージャ|プロジェクトマネージャ&lt;br /&gt;
** システムアーキテクト|システムアーキテクト&lt;br /&gt;
** ITストラテジスト|ITストラテジスト&lt;br /&gt;
** PMBOK|PMBOK&lt;br /&gt;
** BABOK|BABOK&lt;br /&gt;
** システム開発|システム開発&lt;br /&gt;
** ファンクションポイント|ファンクションポイント&lt;br /&gt;
** OpenProj|OpenProj&lt;br /&gt;
** ProjectLibre|ProjectLibre&lt;br /&gt;
** Open Workbench|Open Workbench&lt;br /&gt;
* 仮想化&lt;br /&gt;
** Docker|Docker&lt;br /&gt;
** Hyper-V|Hyper-V&lt;br /&gt;
** Kubernetes|Kubernetes&lt;br /&gt;
** KVM&lt;br /&gt;
** multipass&lt;br /&gt;
** VirtualBox|VirtualBox&lt;br /&gt;
** Xen|Xen&lt;br /&gt;
*Network&lt;br /&gt;
** DNS|DNS&lt;br /&gt;
** TCP／IP|TCP／IP&lt;br /&gt;
** ロードバランサー|ロードバランサー&lt;br /&gt;
* Office&lt;br /&gt;
** Access|Access&lt;br /&gt;
** Excel|Excel&lt;br /&gt;
** Microsoft Project|Microsoft Project&lt;br /&gt;
** Outlook|Outlook&lt;br /&gt;
** PowerPoint|PowerPoint&lt;br /&gt;
** Visio|Visio&lt;br /&gt;
** Word|Word&lt;br /&gt;
*CMS&lt;br /&gt;
** FSWiki|FreeStyle Wiki|FSWiki|FreeStyle Wiki&lt;br /&gt;
** MediaWiki|MediaWiki&lt;br /&gt;
** Movable Type|Movable Type&lt;br /&gt;
** WordPress|WordPress&lt;br /&gt;
*構成管理&lt;br /&gt;
** Git|Git&lt;br /&gt;
** subversion|subversion&lt;br /&gt;
** Vagrant|Vagrant&lt;br /&gt;
** Maven|Maven&lt;br /&gt;
*ツール&lt;br /&gt;
**Hashids|Hashids&lt;br /&gt;
* 文章&lt;br /&gt;
** 接続詞|接続詞&lt;br /&gt;
* 音楽&lt;br /&gt;
** 作詞作曲|作詞作曲&lt;br /&gt;
*教養&lt;br /&gt;
** 論理学|論理学&lt;br /&gt;
** 数学|数学&lt;br /&gt;
** 行列プログラマー|行列プログラマー&lt;br /&gt;
** 統計|統計&lt;br /&gt;
** 自然言語処理|自然言語処理&lt;br /&gt;
* デザイン&lt;br /&gt;
** Inkscape|Inkscape&lt;br /&gt;
** GIMP|GIMP&lt;br /&gt;
* 業務&lt;br /&gt;
** 購買業務|購買業務&lt;br /&gt;
** 設備保全|設備保全&lt;br /&gt;
** 生産管理|生産管理&lt;br /&gt;
** トヨタ生産方式|トヨタ生産方式&lt;br /&gt;
** 部品表|部品表&lt;br /&gt;
** 統合化部品表|統合化部品表&lt;br /&gt;
** 物流|物流&lt;br /&gt;
** DX|DX&lt;br /&gt;
** 在庫管理|在庫管理&lt;br /&gt;
* その他&lt;br /&gt;
** PC|PC&lt;br /&gt;
** OSS|OSS&lt;br /&gt;
** Tips|Tips&lt;br /&gt;
** Webサービス|Webサービス&lt;br /&gt;
** 英語|英語&lt;br /&gt;
** リンク|リンク&lt;br /&gt;
** 本の紹介|本の紹介&lt;br /&gt;
** 引用文|引用文&lt;br /&gt;
** LIFE HACK|LIFE HACK&lt;br /&gt;
** アイディア|アイディア&lt;br /&gt;
** コミュニケーション|コミュニケーション&lt;br /&gt;
** Music Bee|Music Bee&lt;br /&gt;
** Cakewalk|Cakewalk&lt;/div&gt;</summary>
		<author><name>Piroto</name></author>
		
	</entry>
	<entry>
		<id>https://www.typea.info/tips_/index.php?title=Next.js&amp;diff=35359</id>
		<title>Next.js</title>
		<link rel="alternate" type="text/html" href="https://www.typea.info/tips_/index.php?title=Next.js&amp;diff=35359"/>
		<updated>2024-10-06T02:44:59Z</updated>

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

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

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

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

		<summary type="html">&lt;p&gt;Piroto: /* MUI */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[React]] | [[MUI]] |&lt;br /&gt;
&lt;br /&gt;
{{amazon|4815619484}}&lt;br /&gt;
&lt;br /&gt;
=概要=&lt;br /&gt;
*[https://ja.next-community-docs.dev/docs/app-router/getting-started/ Next.js Document]&lt;br /&gt;
*[https://qiita.com/newbee1939/items/7ce919f9a1a7153582b8#:~:text=React%20Serv React Server ComponentsとApp Routerをそろそろちゃんと理解したい]&lt;br /&gt;
*Reactは、あくまでUI部分のみ&lt;br /&gt;
*本格的なアプリ開発には周辺領域を担うためのフレームワークが必要&lt;br /&gt;
*Reactベースのフレームワークとしてデファクトスタンダードと言える存在&lt;br /&gt;
*主なライブラリ&lt;br /&gt;
**ファイルシステムベースの設定レスルーター&lt;br /&gt;
**サーバーコンポーネント&lt;br /&gt;
**データ取得用fetchメソッド&lt;br /&gt;
**リソース組み込みの自動最適化&lt;br /&gt;
**CSSフレームワーク、Tailwind　CSSへの標準対応&lt;br /&gt;
&lt;br /&gt;
=導入=&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
newdelhi:Workspaces piroto$ npx create-next-app@latest&lt;br /&gt;
Need to install the following packages:&lt;br /&gt;
create-next-app@14.2.14&lt;br /&gt;
Ok to proceed? (y) y&lt;br /&gt;
&lt;br /&gt;
✔ What is your project named? … first-nextjs-app&lt;br /&gt;
✔ Would you like to use TypeScript? … No / Yes&lt;br /&gt;
✔ Would you like to use ESLint? … No / Yes&lt;br /&gt;
✔ Would you like to use Tailwind CSS? … No / Yes&lt;br /&gt;
✔ Would you like to use `src/` directory? … No / Yes&lt;br /&gt;
✔ Would you like to use App Router? (recommended) … No / Yes&lt;br /&gt;
✔ Would you like to customize the default import alias (@/*)? … No / Yes&lt;br /&gt;
Creating a new Next.js app in /Users/piroto/Workspaces/first-nextjs-app.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==実行==&lt;br /&gt;
===開発===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
npm run dev&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Start_next_js.png | 300px]]&lt;br /&gt;
&lt;br /&gt;
===本番ビルド＋実行===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
npm run build&lt;br /&gt;
npm start&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
===静的サイトとしてビルドした場合の実行===&lt;br /&gt;
*Prisma でのデータアクセスの処理がビルド時に実行され、その時点の静的な出力になる&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
npm run build&lt;br /&gt;
npx serve@latest out&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====ビルド結果がクリーンされない====&lt;br /&gt;
*https://blog.unimoku.com/20201209&lt;br /&gt;
*/.next /out はビルド時に削除しても良い。&lt;br /&gt;
*デフォルトでクリーンされない&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rm -rf .next out&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==App Router==&lt;br /&gt;
*React Routerとは異なる独自のルーターを標準で提供&lt;br /&gt;
*コンポーネントそのものはReactと変わらない&lt;br /&gt;
&lt;br /&gt;
===2種類のルーター===&lt;br /&gt;
&lt;br /&gt;
*Pages Router : 旧来から提供されている&lt;br /&gt;
*App Router : Next.js 13から導入された新しいルーター(推奨)&lt;br /&gt;
&lt;br /&gt;
====App Router====&lt;br /&gt;
*フォルダベースのルーター&lt;br /&gt;
*ルート定義不要、フォルダ階層に準じてリクエストパスとコンポーネント(.jsファイル)との対応関係が決まる&lt;br /&gt;
*page.jsはファイル名も固定でフォルダー構造だけでリクエストパスが決定される&lt;br /&gt;
*デフォルトで作成したコンポーネントがサーバーコンポーネントになる&lt;br /&gt;
*クライアントコンポーネントにするにはuse clientを記述する必要がある&lt;br /&gt;
&lt;br /&gt;
=====アプリ共通の外枠=====&lt;br /&gt;
*layout.js&lt;br /&gt;
*&amp;amp;lt;html&amp;amp;gt;、&amp;amp;lt;body&amp;amp;gt; 要素が存在し、個々のページを埋め込むため chilrenプロパティを引用していることが条件&lt;br /&gt;
&lt;br /&gt;
===ルートパラメータ===&lt;br /&gt;
*[名前] ： 単一パラメータ&lt;br /&gt;
*[...名前] : キャッチオールセグメント&lt;br /&gt;
*&amp;lt;nowiki&amp;gt;[[...名前]]&amp;lt;/nowiki&amp;gt; : 省略可能なキャッチオールセグメント&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ App Routerのルートパラメータ&lt;br /&gt;
|-&lt;br /&gt;
! フォルダ階層 !! 対応リクエスト !! パラメータ&lt;br /&gt;
|-&lt;br /&gt;
| /app/hoge/[id]/page.js || /hoge/001 || { id : '001' }&lt;br /&gt;
|-&lt;br /&gt;
| /app/foo/[...keys]/page.js || /foo/aaa/bbb || { keys: ['aaa', 'bbb'] }&lt;br /&gt;
|-&lt;br /&gt;
| /app/bar/&amp;lt;nowiki&amp;gt;[[...keys]]&amp;lt;/nowiki&amp;gt;/page.js || /bar || {}&lt;br /&gt;
|-&lt;br /&gt;
| 〃 || /bar/aaa/bbb || { keys: ['aaa', 'bbb'] }&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Tailwind CSS==&lt;br /&gt;
*https://tailwindcss.com/&lt;br /&gt;
*ユーティリティファーストをコンセプトに開発されたCSSフレームワーク&lt;br /&gt;
*ユーティリティを組み合わせてデザインを作るので独自のスタイルを作りやすく細かな調整もしやすいメリット&lt;br /&gt;
*標準のサイズ、カラーなどは用意されている&lt;br /&gt;
&lt;br /&gt;
[https://tailwindcsscheatsheet.com/ Cheat Sheet]&lt;br /&gt;
&lt;br /&gt;
*Tailwind　CSSによるスタイルを適用&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import &amp;quot;./globals.css&amp;quot;;&lt;br /&gt;
    :&lt;br /&gt;
&lt;br /&gt;
&amp;amp;lt;ul className=&amp;quot;fle bg-blue-600 mb-4 pl-2&amp;quot;&amp;amp;gt;...&amp;amp;lt;/ul&amp;amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Prisma==&lt;br /&gt;
*JavaScriptアプリからデータベース操作を取り持つO/Rマッパー&lt;br /&gt;
===インストール===&lt;br /&gt;
*成功すると以下のファイルが生成される&lt;br /&gt;
**.env : 環境変数ファイル、gitignore に追加する&lt;br /&gt;
** prisma/schema.prisma : Prismaのスキーマファイル&lt;br /&gt;
&lt;br /&gt;
sqliteでの構成例&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ npm install prisma --save-dev&lt;br /&gt;
 $ npx prisma init --datasource-provider sqlite&lt;br /&gt;
 warn You already have a .gitignore file. Don't forget to add `.env` in it to not commit any private information.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===データモデルの定義===&lt;br /&gt;
*prisma/schema.prisma に追記&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
model　reviews {&lt;br /&gt;
  id          String @id&lt;br /&gt;
  title       String&lt;br /&gt;
  author      String&lt;br /&gt;
  price       Int&lt;br /&gt;
  publlisher  String&lt;br /&gt;
  published   String&lt;br /&gt;
  image       String&lt;br /&gt;
  read        DateTime  @default(now())&lt;br /&gt;
  memo        String&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*DBに反映&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ npx prisma db push&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Prisma Studio(Webベース管理ツール)で確認&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ npx prisma studio&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Error: @prisma/client did not initialize yet. Please run &amp;quot;prisma generate&amp;quot; and try to import it again.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ nps prisma generate&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import { PrismaClient } from &amp;quot;@prisma/client&amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Prisma Clientの利用&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import { PrismaClient } from &amp;quot;@prisma/client&amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==サーバーアクション==&lt;br /&gt;
*Next.js内蔵の仕組み&lt;br /&gt;
*ページコンポーネント、イベントハンドラー、&amp;amp;lt;form&amp;amp;lt;要素のaction属性などからサーバーコードを呼び出す仕組み&lt;br /&gt;
*サーバーとのやりとりに際し、fetchなどの非同期通信コードの不要となり、例えばコンポーネントからデータベースを操作するにも直感的なコードを記述できる&lt;br /&gt;
*現時点ではα版&lt;br /&gt;
&lt;br /&gt;
===有効化===&lt;br /&gt;
&lt;br /&gt;
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]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
const nextConfig = {&lt;br /&gt;
    experimental: {&lt;br /&gt;
        serverActions: true&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=コンポーネントの処理=&lt;br /&gt;
*[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 サーバーとクライアントの構成パターン]&lt;br /&gt;
&lt;br /&gt;
==サーバー側で実行==&lt;br /&gt;
*Next.jsの基本はサーバー側でコンポーネントを処理&lt;br /&gt;
*[https://www.ey-office.com/blog_archive/2024/05/29/tried-running-react-server-component-in-a-production-environment-and-got-a-little-hooked/ 本番環境で動かす]&lt;br /&gt;
*メリット&lt;br /&gt;
**サーバーリソースの活用&lt;br /&gt;
**ダウンロードコードサイズの最小化&lt;br /&gt;
**機密情報(サクセストークンなど)の管理&lt;br /&gt;
*クライアントに依存する操作には対応していない&lt;br /&gt;
**State関連操作(useState,useReducer,useEffectなど)&lt;br /&gt;
**イベントリスナー(onXxxxx)&lt;br /&gt;
**ブラウザAPIアクセス&lt;br /&gt;
**上記を伴うカスタムフック&lt;br /&gt;
**クラスコンポーネント利用&lt;br /&gt;
&lt;br /&gt;
==クライアント側で実行==&lt;br /&gt;
*ファイルの先頭に、'use client'ディレクティブを記述することでコンポーネントをクライアント側で実行可&lt;br /&gt;
&lt;br /&gt;
==静的サイト==&lt;br /&gt;
*[https://zenn.dev/hiromu617/articles/1ed6811dc6cf26 静的サイトの生成]&lt;br /&gt;
*静的エクスポートを有効にすることによりビルド時の生成物がNode.jsサーバーを必要としないものとなる&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
const nextConfig = {&lt;br /&gt;
    :&lt;br /&gt;
    output: 'export'&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
*この機能を有効にすることで、ridirectsやmiddlewareなどのサーバーを必要とする一部機能が使えなくなります&lt;br /&gt;
*動的レンダリングも一切できなくなってしまうのでこの機能を有効にするかはアプリケーションの性質を考慮して検討&lt;br /&gt;
&lt;br /&gt;
=実装=&lt;br /&gt;
&lt;br /&gt;
==ルートレイアウト==&lt;br /&gt;
===アプリ内のリンクにはLinkコンポーネントを利用===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import Link from &amp;quot;next/link&amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
規定で以下のようなコンポーネントが用意されており、アプリ内リソースを効率的に利用できる&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ コンポーネント&lt;br /&gt;
|-&lt;br /&gt;
! コンポーネント !! 概要&lt;br /&gt;
|-&lt;br /&gt;
| &amp;amp;lt;Link&amp;amp;gt; || リンクを生成&lt;br /&gt;
|-&lt;br /&gt;
| &amp;amp;lt;Script&amp;amp;gt; || スクリプトのロード&lt;br /&gt;
|-&lt;br /&gt;
| &amp;amp;lt;Image&amp;amp;gt; || 画像を表示&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===メタデータ===&lt;br /&gt;
*メタデータを定義しておくことで、個々のページに適切なヘッダーなどを埋め込める&lt;br /&gt;
*複数箇所で宣言された場合、シャローマージされる&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
export const metadata: Metadata = {&lt;br /&gt;
  title: &amp;quot;Reading Recorder&amp;quot;,&lt;br /&gt;
  description: &amp;quot;自分が読んだ書籍の記録を残す&amp;quot;,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*generateMetadata関数を利用しデータベースなどから取得した結果を元に動的に生成も可能&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
export async function generateMetadata({ params, searchParams }) {&lt;br /&gt;
    :&lt;br /&gt;
    return {&lt;br /&gt;
        title : result.title,&lt;br /&gt;
            :&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Route Segment Config===&lt;br /&gt;
*https://nextjs.org/docs/app/api-reference/file-conventions/route-segment-config&lt;br /&gt;
*レイアウト、ページ単位の設定 &lt;br /&gt;
*あらかじめ決められた名前の変数をエクスポートしておくことで、個別の設定を施せる&lt;br /&gt;
*force-dynamic : 極力キャッシュを無効にし、ページを動的に描画しようとする&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
export const dynamic = 'force-dynamic'&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=フォント=&lt;br /&gt;
*Googleフォント(無償フォントのディレクトリサービス)を有効化&lt;br /&gt;
*具体的なフォントはGoogleフォントから自由に選択できるが一般的にはバリアブルフォント推奨(下例ではInconsolata)&lt;br /&gt;
*フォントはファイルサイズが大きいので、subsetで利用する文字のみ取り出す&lt;br /&gt;
*fnc.className でフォントを適用できる&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import { Inconsolata } from 'next/font/google';&lt;br /&gt;
const fnt = Inconsolata({ subsets: ['latin'] });&lt;br /&gt;
&lt;br /&gt;
  :&lt;br /&gt;
&amp;amp;lt;body className={`${fnt.className}` }&amp;amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=MUI=&lt;br /&gt;
[[MUI]]&lt;br /&gt;
&lt;br /&gt;
=外部サービスからのデータ取得=&lt;br /&gt;
*標準JavaScriptのfetchが拡張されている&lt;br /&gt;
*関数コンポーネントを非同期(async)とすることでコンポーネント配下でfetchメソッドを実行できる&lt;br /&gt;
*個々のfetch呼び出しに際して、キャッシュ/再取得ルールを指定できる&lt;br /&gt;
*コンポーネント改装間で同一データを取得の場合、リクエストの重複を除去&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
fetch('https://...&amp;quot;, { cache: 'force-cache' }); // 無制限にキャッシュ&lt;br /&gt;
fetch('https://...&amp;quot;); // 無制限にキャッシュ&lt;br /&gt;
fetch('https://...&amp;quot;, { cache: 'no-store' }); // 常にデータを取得&lt;br /&gt;
fetch('https://...&amp;quot;, { cache: 'revalidate: 10' }); // 10秒以上でデータを再取得&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Tips=&lt;br /&gt;
&lt;br /&gt;
==リモートホストからの画像表示を許可する==&lt;br /&gt;
*next.config.mjs&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
const nextConfig = {&lt;br /&gt;
&lt;br /&gt;
    :&lt;br /&gt;
&lt;br /&gt;
    images: {&lt;br /&gt;
        remotePatterns: [&lt;br /&gt;
            {&lt;br /&gt;
                hostname: 'books.google.com'&lt;br /&gt;
            } &lt;br /&gt;
        ] &lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Piroto</name></author>
		
	</entry>
	<entry>
		<id>https://www.typea.info/tips_/index.php?title=Next.js&amp;diff=35354</id>
		<title>Next.js</title>
		<link rel="alternate" type="text/html" href="https://www.typea.info/tips_/index.php?title=Next.js&amp;diff=35354"/>
		<updated>2024-10-05T16:43:16Z</updated>

		<summary type="html">&lt;p&gt;Piroto: /* 本番ビルド＋実行 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[React]] | [[MUI]] |&lt;br /&gt;
&lt;br /&gt;
{{amazon|4815619484}}&lt;br /&gt;
&lt;br /&gt;
=概要=&lt;br /&gt;
*[https://ja.next-community-docs.dev/docs/app-router/getting-started/ Next.js Document]&lt;br /&gt;
*[https://qiita.com/newbee1939/items/7ce919f9a1a7153582b8#:~:text=React%20Serv React Server ComponentsとApp Routerをそろそろちゃんと理解したい]&lt;br /&gt;
*Reactは、あくまでUI部分のみ&lt;br /&gt;
*本格的なアプリ開発には周辺領域を担うためのフレームワークが必要&lt;br /&gt;
*Reactベースのフレームワークとしてデファクトスタンダードと言える存在&lt;br /&gt;
*主なライブラリ&lt;br /&gt;
**ファイルシステムベースの設定レスルーター&lt;br /&gt;
**サーバーコンポーネント&lt;br /&gt;
**データ取得用fetchメソッド&lt;br /&gt;
**リソース組み込みの自動最適化&lt;br /&gt;
**CSSフレームワーク、Tailwind　CSSへの標準対応&lt;br /&gt;
&lt;br /&gt;
=導入=&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
newdelhi:Workspaces piroto$ npx create-next-app@latest&lt;br /&gt;
Need to install the following packages:&lt;br /&gt;
create-next-app@14.2.14&lt;br /&gt;
Ok to proceed? (y) y&lt;br /&gt;
&lt;br /&gt;
✔ What is your project named? … first-nextjs-app&lt;br /&gt;
✔ Would you like to use TypeScript? … No / Yes&lt;br /&gt;
✔ Would you like to use ESLint? … No / Yes&lt;br /&gt;
✔ Would you like to use Tailwind CSS? … No / Yes&lt;br /&gt;
✔ Would you like to use `src/` directory? … No / Yes&lt;br /&gt;
✔ Would you like to use App Router? (recommended) … No / Yes&lt;br /&gt;
✔ Would you like to customize the default import alias (@/*)? … No / Yes&lt;br /&gt;
Creating a new Next.js app in /Users/piroto/Workspaces/first-nextjs-app.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==実行==&lt;br /&gt;
===開発===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
npm run dev&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Start_next_js.png | 300px]]&lt;br /&gt;
&lt;br /&gt;
===本番ビルド＋実行===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
npm run build&lt;br /&gt;
npm start&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
===静的サイトとしてビルドした場合の実行===&lt;br /&gt;
*Prisma でのデータアクセスの処理がビルド時に実行され、その時点の静的な出力になる&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
npm run build&lt;br /&gt;
npx serve@latest out&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====ビルド結果がクリーンされない====&lt;br /&gt;
*https://blog.unimoku.com/20201209&lt;br /&gt;
*/.next /out はビルド時に削除しても良い。&lt;br /&gt;
*デフォルトでクリーンされない&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rm -rf .next out&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==App Router==&lt;br /&gt;
*React Routerとは異なる独自のルーターを標準で提供&lt;br /&gt;
*コンポーネントそのものはReactと変わらない&lt;br /&gt;
&lt;br /&gt;
===2種類のルーター===&lt;br /&gt;
&lt;br /&gt;
*Pages Router : 旧来から提供されている&lt;br /&gt;
*App Router : Next.js 13から導入された新しいルーター(推奨)&lt;br /&gt;
&lt;br /&gt;
====App Router====&lt;br /&gt;
*フォルダベースのルーター&lt;br /&gt;
*ルート定義不要、フォルダ階層に準じてリクエストパスとコンポーネント(.jsファイル)との対応関係が決まる&lt;br /&gt;
*page.jsはファイル名も固定でフォルダー構造だけでリクエストパスが決定される&lt;br /&gt;
*デフォルトで作成したコンポーネントがサーバーコンポーネントになる&lt;br /&gt;
*クライアントコンポーネントにするにはuse clientを記述する必要がある&lt;br /&gt;
&lt;br /&gt;
=====アプリ共通の外枠=====&lt;br /&gt;
*layout.js&lt;br /&gt;
*&amp;amp;lt;html&amp;amp;gt;、&amp;amp;lt;body&amp;amp;gt; 要素が存在し、個々のページを埋め込むため chilrenプロパティを引用していることが条件&lt;br /&gt;
&lt;br /&gt;
===ルートパラメータ===&lt;br /&gt;
*[名前] ： 単一パラメータ&lt;br /&gt;
*[...名前] : キャッチオールセグメント&lt;br /&gt;
*&amp;lt;nowiki&amp;gt;[[...名前]]&amp;lt;/nowiki&amp;gt; : 省略可能なキャッチオールセグメント&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ App Routerのルートパラメータ&lt;br /&gt;
|-&lt;br /&gt;
! フォルダ階層 !! 対応リクエスト !! パラメータ&lt;br /&gt;
|-&lt;br /&gt;
| /app/hoge/[id]/page.js || /hoge/001 || { id : '001' }&lt;br /&gt;
|-&lt;br /&gt;
| /app/foo/[...keys]/page.js || /foo/aaa/bbb || { keys: ['aaa', 'bbb'] }&lt;br /&gt;
|-&lt;br /&gt;
| /app/bar/&amp;lt;nowiki&amp;gt;[[...keys]]&amp;lt;/nowiki&amp;gt;/page.js || /bar || {}&lt;br /&gt;
|-&lt;br /&gt;
| 〃 || /bar/aaa/bbb || { keys: ['aaa', 'bbb'] }&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Tailwind CSS==&lt;br /&gt;
*https://tailwindcss.com/&lt;br /&gt;
*ユーティリティファーストをコンセプトに開発されたCSSフレームワーク&lt;br /&gt;
*ユーティリティを組み合わせてデザインを作るので独自のスタイルを作りやすく細かな調整もしやすいメリット&lt;br /&gt;
*標準のサイズ、カラーなどは用意されている&lt;br /&gt;
&lt;br /&gt;
[https://tailwindcsscheatsheet.com/ Cheat Sheet]&lt;br /&gt;
&lt;br /&gt;
*Tailwind　CSSによるスタイルを適用&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import &amp;quot;./globals.css&amp;quot;;&lt;br /&gt;
    :&lt;br /&gt;
&lt;br /&gt;
&amp;amp;lt;ul className=&amp;quot;fle bg-blue-600 mb-4 pl-2&amp;quot;&amp;amp;gt;...&amp;amp;lt;/ul&amp;amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Prisma==&lt;br /&gt;
*JavaScriptアプリからデータベース操作を取り持つO/Rマッパー&lt;br /&gt;
===インストール===&lt;br /&gt;
*成功すると以下のファイルが生成される&lt;br /&gt;
**.env : 環境変数ファイル、gitignore に追加する&lt;br /&gt;
** prisma/schema.prisma : Prismaのスキーマファイル&lt;br /&gt;
&lt;br /&gt;
sqliteでの構成例&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ npm install prisma --save-dev&lt;br /&gt;
 $ npx prisma init --datasource-provider sqlite&lt;br /&gt;
 warn You already have a .gitignore file. Don't forget to add `.env` in it to not commit any private information.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===データモデルの定義===&lt;br /&gt;
*prisma/schema.prisma に追記&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
model　reviews {&lt;br /&gt;
  id          String @id&lt;br /&gt;
  title       String&lt;br /&gt;
  author      String&lt;br /&gt;
  price       Int&lt;br /&gt;
  publlisher  String&lt;br /&gt;
  published   String&lt;br /&gt;
  image       String&lt;br /&gt;
  read        DateTime  @default(now())&lt;br /&gt;
  memo        String&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*DBに反映&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ npx prisma db push&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Prisma Studio(Webベース管理ツール)で確認&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ npx prisma studio&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Error: @prisma/client did not initialize yet. Please run &amp;quot;prisma generate&amp;quot; and try to import it again.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ nps prisma generate&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import { PrismaClient } from &amp;quot;@prisma/client&amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Prisma Clientの利用&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import { PrismaClient } from &amp;quot;@prisma/client&amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==サーバーアクション==&lt;br /&gt;
*Next.js内蔵の仕組み&lt;br /&gt;
*ページコンポーネント、イベントハンドラー、&amp;amp;lt;form&amp;amp;lt;要素のaction属性などからサーバーコードを呼び出す仕組み&lt;br /&gt;
*サーバーとのやりとりに際し、fetchなどの非同期通信コードの不要となり、例えばコンポーネントからデータベースを操作するにも直感的なコードを記述できる&lt;br /&gt;
*現時点ではα版&lt;br /&gt;
&lt;br /&gt;
===有効化===&lt;br /&gt;
&lt;br /&gt;
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]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
const nextConfig = {&lt;br /&gt;
    experimental: {&lt;br /&gt;
        serverActions: true&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=コンポーネントの処理=&lt;br /&gt;
*[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 サーバーとクライアントの構成パターン]&lt;br /&gt;
&lt;br /&gt;
==サーバー側で実行==&lt;br /&gt;
*Next.jsの基本はサーバー側でコンポーネントを処理&lt;br /&gt;
*[https://www.ey-office.com/blog_archive/2024/05/29/tried-running-react-server-component-in-a-production-environment-and-got-a-little-hooked/ 本番環境で動かす]&lt;br /&gt;
*メリット&lt;br /&gt;
**サーバーリソースの活用&lt;br /&gt;
**ダウンロードコードサイズの最小化&lt;br /&gt;
**機密情報(サクセストークンなど)の管理&lt;br /&gt;
*クライアントに依存する操作には対応していない&lt;br /&gt;
**State関連操作(useState,useReducer,useEffectなど)&lt;br /&gt;
**イベントリスナー(onXxxxx)&lt;br /&gt;
**ブラウザAPIアクセス&lt;br /&gt;
**上記を伴うカスタムフック&lt;br /&gt;
**クラスコンポーネント利用&lt;br /&gt;
&lt;br /&gt;
==クライアント側で実行==&lt;br /&gt;
*ファイルの先頭に、'use client'ディレクティブを記述することでコンポーネントをクライアント側で実行可&lt;br /&gt;
&lt;br /&gt;
==静的サイト==&lt;br /&gt;
*[https://zenn.dev/hiromu617/articles/1ed6811dc6cf26 静的サイトの生成]&lt;br /&gt;
*静的エクスポートを有効にすることによりビルド時の生成物がNode.jsサーバーを必要としないものとなる&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
const nextConfig = {&lt;br /&gt;
    :&lt;br /&gt;
    output: 'export'&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
*この機能を有効にすることで、ridirectsやmiddlewareなどのサーバーを必要とする一部機能が使えなくなります&lt;br /&gt;
*動的レンダリングも一切できなくなってしまうのでこの機能を有効にするかはアプリケーションの性質を考慮して検討&lt;br /&gt;
&lt;br /&gt;
=実装=&lt;br /&gt;
&lt;br /&gt;
==ルートレイアウト==&lt;br /&gt;
===アプリ内のリンクにはLinkコンポーネントを利用===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import Link from &amp;quot;next/link&amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
規定で以下のようなコンポーネントが用意されており、アプリ内リソースを効率的に利用できる&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ コンポーネント&lt;br /&gt;
|-&lt;br /&gt;
! コンポーネント !! 概要&lt;br /&gt;
|-&lt;br /&gt;
| &amp;amp;lt;Link&amp;amp;gt; || リンクを生成&lt;br /&gt;
|-&lt;br /&gt;
| &amp;amp;lt;Script&amp;amp;gt; || スクリプトのロード&lt;br /&gt;
|-&lt;br /&gt;
| &amp;amp;lt;Image&amp;amp;gt; || 画像を表示&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===メタデータ===&lt;br /&gt;
*メタデータを定義しておくことで、個々のページに適切なヘッダーなどを埋め込める&lt;br /&gt;
*複数箇所で宣言された場合、シャローマージされる&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
export const metadata: Metadata = {&lt;br /&gt;
  title: &amp;quot;Reading Recorder&amp;quot;,&lt;br /&gt;
  description: &amp;quot;自分が読んだ書籍の記録を残す&amp;quot;,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*generateMetadata関数を利用しデータベースなどから取得した結果を元に動的に生成も可能&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
export async function generateMetadata({ params, searchParams }) {&lt;br /&gt;
    :&lt;br /&gt;
    return {&lt;br /&gt;
        title : result.title,&lt;br /&gt;
            :&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Route Segment Config===&lt;br /&gt;
*https://nextjs.org/docs/app/api-reference/file-conventions/route-segment-config&lt;br /&gt;
*レイアウト、ページ単位の設定 &lt;br /&gt;
*あらかじめ決められた名前の変数をエクスポートしておくことで、個別の設定を施せる&lt;br /&gt;
*force-dynamic : 極力キャッシュを無効にし、ページを動的に描画しようとする&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
export const dynamic = 'force-dynamic'&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=フォント=&lt;br /&gt;
*Googleフォント(無償フォントのディレクトリサービス)を有効化&lt;br /&gt;
*具体的なフォントはGoogleフォントから自由に選択できるが一般的にはバリアブルフォント推奨(下例ではInconsolata)&lt;br /&gt;
*フォントはファイルサイズが大きいので、subsetで利用する文字のみ取り出す&lt;br /&gt;
*fnc.className でフォントを適用できる&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import { Inconsolata } from 'next/font/google';&lt;br /&gt;
const fnt = Inconsolata({ subsets: ['latin'] });&lt;br /&gt;
&lt;br /&gt;
  :&lt;br /&gt;
&amp;amp;lt;body className={`${fnt.className}` }&amp;amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=MUI=&lt;br /&gt;
[[MUI]]&lt;br /&gt;
&lt;br /&gt;
=Tips=&lt;br /&gt;
&lt;br /&gt;
==リモートホストからの画像表示を許可する==&lt;br /&gt;
*next.config.mjs&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
const nextConfig = {&lt;br /&gt;
&lt;br /&gt;
    :&lt;br /&gt;
&lt;br /&gt;
    images: {&lt;br /&gt;
        remotePatterns: [&lt;br /&gt;
            {&lt;br /&gt;
                hostname: 'books.google.com'&lt;br /&gt;
            } &lt;br /&gt;
        ] &lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Piroto</name></author>
		
	</entry>
	<entry>
		<id>https://www.typea.info/tips_/index.php?title=Next.js&amp;diff=35353</id>
		<title>Next.js</title>
		<link rel="alternate" type="text/html" href="https://www.typea.info/tips_/index.php?title=Next.js&amp;diff=35353"/>
		<updated>2024-10-05T16:31:47Z</updated>

		<summary type="html">&lt;p&gt;Piroto: /* 本番ビルド＋実行 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[React]] | [[MUI]] |&lt;br /&gt;
&lt;br /&gt;
{{amazon|4815619484}}&lt;br /&gt;
&lt;br /&gt;
=概要=&lt;br /&gt;
*[https://ja.next-community-docs.dev/docs/app-router/getting-started/ Next.js Document]&lt;br /&gt;
*[https://qiita.com/newbee1939/items/7ce919f9a1a7153582b8#:~:text=React%20Serv React Server ComponentsとApp Routerをそろそろちゃんと理解したい]&lt;br /&gt;
*Reactは、あくまでUI部分のみ&lt;br /&gt;
*本格的なアプリ開発には周辺領域を担うためのフレームワークが必要&lt;br /&gt;
*Reactベースのフレームワークとしてデファクトスタンダードと言える存在&lt;br /&gt;
*主なライブラリ&lt;br /&gt;
**ファイルシステムベースの設定レスルーター&lt;br /&gt;
**サーバーコンポーネント&lt;br /&gt;
**データ取得用fetchメソッド&lt;br /&gt;
**リソース組み込みの自動最適化&lt;br /&gt;
**CSSフレームワーク、Tailwind　CSSへの標準対応&lt;br /&gt;
&lt;br /&gt;
=導入=&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
newdelhi:Workspaces piroto$ npx create-next-app@latest&lt;br /&gt;
Need to install the following packages:&lt;br /&gt;
create-next-app@14.2.14&lt;br /&gt;
Ok to proceed? (y) y&lt;br /&gt;
&lt;br /&gt;
✔ What is your project named? … first-nextjs-app&lt;br /&gt;
✔ Would you like to use TypeScript? … No / Yes&lt;br /&gt;
✔ Would you like to use ESLint? … No / Yes&lt;br /&gt;
✔ Would you like to use Tailwind CSS? … No / Yes&lt;br /&gt;
✔ Would you like to use `src/` directory? … No / Yes&lt;br /&gt;
✔ Would you like to use App Router? (recommended) … No / Yes&lt;br /&gt;
✔ Would you like to customize the default import alias (@/*)? … No / Yes&lt;br /&gt;
Creating a new Next.js app in /Users/piroto/Workspaces/first-nextjs-app.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==実行==&lt;br /&gt;
===開発===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
npm run dev&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Start_next_js.png | 300px]]&lt;br /&gt;
&lt;br /&gt;
===本番ビルド＋実行===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
npm run build&lt;br /&gt;
npm start&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
*静的サイトとしてビルドした場合の実行&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
npm run build&lt;br /&gt;
npx serve@latest out&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====ビルド結果がクリーンされない====&lt;br /&gt;
*https://blog.unimoku.com/20201209&lt;br /&gt;
*/.next /out はビルド時に削除しても良い。&lt;br /&gt;
*デフォルトでクリーンされない&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rm -rf .next out&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==App Router==&lt;br /&gt;
*React Routerとは異なる独自のルーターを標準で提供&lt;br /&gt;
*コンポーネントそのものはReactと変わらない&lt;br /&gt;
&lt;br /&gt;
===2種類のルーター===&lt;br /&gt;
&lt;br /&gt;
*Pages Router : 旧来から提供されている&lt;br /&gt;
*App Router : Next.js 13から導入された新しいルーター(推奨)&lt;br /&gt;
&lt;br /&gt;
====App Router====&lt;br /&gt;
*フォルダベースのルーター&lt;br /&gt;
*ルート定義不要、フォルダ階層に準じてリクエストパスとコンポーネント(.jsファイル)との対応関係が決まる&lt;br /&gt;
*page.jsはファイル名も固定でフォルダー構造だけでリクエストパスが決定される&lt;br /&gt;
*デフォルトで作成したコンポーネントがサーバーコンポーネントになる&lt;br /&gt;
*クライアントコンポーネントにするにはuse clientを記述する必要がある&lt;br /&gt;
&lt;br /&gt;
=====アプリ共通の外枠=====&lt;br /&gt;
*layout.js&lt;br /&gt;
*&amp;amp;lt;html&amp;amp;gt;、&amp;amp;lt;body&amp;amp;gt; 要素が存在し、個々のページを埋め込むため chilrenプロパティを引用していることが条件&lt;br /&gt;
&lt;br /&gt;
===ルートパラメータ===&lt;br /&gt;
*[名前] ： 単一パラメータ&lt;br /&gt;
*[...名前] : キャッチオールセグメント&lt;br /&gt;
*&amp;lt;nowiki&amp;gt;[[...名前]]&amp;lt;/nowiki&amp;gt; : 省略可能なキャッチオールセグメント&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ App Routerのルートパラメータ&lt;br /&gt;
|-&lt;br /&gt;
! フォルダ階層 !! 対応リクエスト !! パラメータ&lt;br /&gt;
|-&lt;br /&gt;
| /app/hoge/[id]/page.js || /hoge/001 || { id : '001' }&lt;br /&gt;
|-&lt;br /&gt;
| /app/foo/[...keys]/page.js || /foo/aaa/bbb || { keys: ['aaa', 'bbb'] }&lt;br /&gt;
|-&lt;br /&gt;
| /app/bar/&amp;lt;nowiki&amp;gt;[[...keys]]&amp;lt;/nowiki&amp;gt;/page.js || /bar || {}&lt;br /&gt;
|-&lt;br /&gt;
| 〃 || /bar/aaa/bbb || { keys: ['aaa', 'bbb'] }&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Tailwind CSS==&lt;br /&gt;
*https://tailwindcss.com/&lt;br /&gt;
*ユーティリティファーストをコンセプトに開発されたCSSフレームワーク&lt;br /&gt;
*ユーティリティを組み合わせてデザインを作るので独自のスタイルを作りやすく細かな調整もしやすいメリット&lt;br /&gt;
*標準のサイズ、カラーなどは用意されている&lt;br /&gt;
&lt;br /&gt;
[https://tailwindcsscheatsheet.com/ Cheat Sheet]&lt;br /&gt;
&lt;br /&gt;
*Tailwind　CSSによるスタイルを適用&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import &amp;quot;./globals.css&amp;quot;;&lt;br /&gt;
    :&lt;br /&gt;
&lt;br /&gt;
&amp;amp;lt;ul className=&amp;quot;fle bg-blue-600 mb-4 pl-2&amp;quot;&amp;amp;gt;...&amp;amp;lt;/ul&amp;amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Prisma==&lt;br /&gt;
*JavaScriptアプリからデータベース操作を取り持つO/Rマッパー&lt;br /&gt;
===インストール===&lt;br /&gt;
*成功すると以下のファイルが生成される&lt;br /&gt;
**.env : 環境変数ファイル、gitignore に追加する&lt;br /&gt;
** prisma/schema.prisma : Prismaのスキーマファイル&lt;br /&gt;
&lt;br /&gt;
sqliteでの構成例&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ npm install prisma --save-dev&lt;br /&gt;
 $ npx prisma init --datasource-provider sqlite&lt;br /&gt;
 warn You already have a .gitignore file. Don't forget to add `.env` in it to not commit any private information.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===データモデルの定義===&lt;br /&gt;
*prisma/schema.prisma に追記&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
model　reviews {&lt;br /&gt;
  id          String @id&lt;br /&gt;
  title       String&lt;br /&gt;
  author      String&lt;br /&gt;
  price       Int&lt;br /&gt;
  publlisher  String&lt;br /&gt;
  published   String&lt;br /&gt;
  image       String&lt;br /&gt;
  read        DateTime  @default(now())&lt;br /&gt;
  memo        String&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*DBに反映&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ npx prisma db push&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Prisma Studio(Webベース管理ツール)で確認&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ npx prisma studio&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Error: @prisma/client did not initialize yet. Please run &amp;quot;prisma generate&amp;quot; and try to import it again.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ nps prisma generate&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import { PrismaClient } from &amp;quot;@prisma/client&amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Prisma Clientの利用&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import { PrismaClient } from &amp;quot;@prisma/client&amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==サーバーアクション==&lt;br /&gt;
*Next.js内蔵の仕組み&lt;br /&gt;
*ページコンポーネント、イベントハンドラー、&amp;amp;lt;form&amp;amp;lt;要素のaction属性などからサーバーコードを呼び出す仕組み&lt;br /&gt;
*サーバーとのやりとりに際し、fetchなどの非同期通信コードの不要となり、例えばコンポーネントからデータベースを操作するにも直感的なコードを記述できる&lt;br /&gt;
*現時点ではα版&lt;br /&gt;
&lt;br /&gt;
===有効化===&lt;br /&gt;
&lt;br /&gt;
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]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
const nextConfig = {&lt;br /&gt;
    experimental: {&lt;br /&gt;
        serverActions: true&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=コンポーネントの処理=&lt;br /&gt;
*[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 サーバーとクライアントの構成パターン]&lt;br /&gt;
&lt;br /&gt;
==サーバー側で実行==&lt;br /&gt;
*Next.jsの基本はサーバー側でコンポーネントを処理&lt;br /&gt;
*[https://www.ey-office.com/blog_archive/2024/05/29/tried-running-react-server-component-in-a-production-environment-and-got-a-little-hooked/ 本番環境で動かす]&lt;br /&gt;
*メリット&lt;br /&gt;
**サーバーリソースの活用&lt;br /&gt;
**ダウンロードコードサイズの最小化&lt;br /&gt;
**機密情報(サクセストークンなど)の管理&lt;br /&gt;
*クライアントに依存する操作には対応していない&lt;br /&gt;
**State関連操作(useState,useReducer,useEffectなど)&lt;br /&gt;
**イベントリスナー(onXxxxx)&lt;br /&gt;
**ブラウザAPIアクセス&lt;br /&gt;
**上記を伴うカスタムフック&lt;br /&gt;
**クラスコンポーネント利用&lt;br /&gt;
&lt;br /&gt;
==クライアント側で実行==&lt;br /&gt;
*ファイルの先頭に、'use client'ディレクティブを記述することでコンポーネントをクライアント側で実行可&lt;br /&gt;
&lt;br /&gt;
==静的サイト==&lt;br /&gt;
*[https://zenn.dev/hiromu617/articles/1ed6811dc6cf26 静的サイトの生成]&lt;br /&gt;
*静的エクスポートを有効にすることによりビルド時の生成物がNode.jsサーバーを必要としないものとなる&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
const nextConfig = {&lt;br /&gt;
    :&lt;br /&gt;
    output: 'export'&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
*この機能を有効にすることで、ridirectsやmiddlewareなどのサーバーを必要とする一部機能が使えなくなります&lt;br /&gt;
*動的レンダリングも一切できなくなってしまうのでこの機能を有効にするかはアプリケーションの性質を考慮して検討&lt;br /&gt;
&lt;br /&gt;
=実装=&lt;br /&gt;
&lt;br /&gt;
==ルートレイアウト==&lt;br /&gt;
===アプリ内のリンクにはLinkコンポーネントを利用===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import Link from &amp;quot;next/link&amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
規定で以下のようなコンポーネントが用意されており、アプリ内リソースを効率的に利用できる&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ コンポーネント&lt;br /&gt;
|-&lt;br /&gt;
! コンポーネント !! 概要&lt;br /&gt;
|-&lt;br /&gt;
| &amp;amp;lt;Link&amp;amp;gt; || リンクを生成&lt;br /&gt;
|-&lt;br /&gt;
| &amp;amp;lt;Script&amp;amp;gt; || スクリプトのロード&lt;br /&gt;
|-&lt;br /&gt;
| &amp;amp;lt;Image&amp;amp;gt; || 画像を表示&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===メタデータ===&lt;br /&gt;
*メタデータを定義しておくことで、個々のページに適切なヘッダーなどを埋め込める&lt;br /&gt;
*複数箇所で宣言された場合、シャローマージされる&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
export const metadata: Metadata = {&lt;br /&gt;
  title: &amp;quot;Reading Recorder&amp;quot;,&lt;br /&gt;
  description: &amp;quot;自分が読んだ書籍の記録を残す&amp;quot;,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*generateMetadata関数を利用しデータベースなどから取得した結果を元に動的に生成も可能&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
export async function generateMetadata({ params, searchParams }) {&lt;br /&gt;
    :&lt;br /&gt;
    return {&lt;br /&gt;
        title : result.title,&lt;br /&gt;
            :&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Route Segment Config===&lt;br /&gt;
*https://nextjs.org/docs/app/api-reference/file-conventions/route-segment-config&lt;br /&gt;
*レイアウト、ページ単位の設定 &lt;br /&gt;
*あらかじめ決められた名前の変数をエクスポートしておくことで、個別の設定を施せる&lt;br /&gt;
*force-dynamic : 極力キャッシュを無効にし、ページを動的に描画しようとする&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
export const dynamic = 'force-dynamic'&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=フォント=&lt;br /&gt;
*Googleフォント(無償フォントのディレクトリサービス)を有効化&lt;br /&gt;
*具体的なフォントはGoogleフォントから自由に選択できるが一般的にはバリアブルフォント推奨(下例ではInconsolata)&lt;br /&gt;
*フォントはファイルサイズが大きいので、subsetで利用する文字のみ取り出す&lt;br /&gt;
*fnc.className でフォントを適用できる&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import { Inconsolata } from 'next/font/google';&lt;br /&gt;
const fnt = Inconsolata({ subsets: ['latin'] });&lt;br /&gt;
&lt;br /&gt;
  :&lt;br /&gt;
&amp;amp;lt;body className={`${fnt.className}` }&amp;amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=MUI=&lt;br /&gt;
[[MUI]]&lt;br /&gt;
&lt;br /&gt;
=Tips=&lt;br /&gt;
&lt;br /&gt;
==リモートホストからの画像表示を許可する==&lt;br /&gt;
*next.config.mjs&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
const nextConfig = {&lt;br /&gt;
&lt;br /&gt;
    :&lt;br /&gt;
&lt;br /&gt;
    images: {&lt;br /&gt;
        remotePatterns: [&lt;br /&gt;
            {&lt;br /&gt;
                hostname: 'books.google.com'&lt;br /&gt;
            } &lt;br /&gt;
        ] &lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Piroto</name></author>
		
	</entry>
	<entry>
		<id>https://www.typea.info/tips_/index.php?title=Next.js&amp;diff=35352</id>
		<title>Next.js</title>
		<link rel="alternate" type="text/html" href="https://www.typea.info/tips_/index.php?title=Next.js&amp;diff=35352"/>
		<updated>2024-10-05T16:27:18Z</updated>

		<summary type="html">&lt;p&gt;Piroto: /* 本番ビルド＋実行 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[React]] | [[MUI]] |&lt;br /&gt;
&lt;br /&gt;
{{amazon|4815619484}}&lt;br /&gt;
&lt;br /&gt;
=概要=&lt;br /&gt;
*[https://ja.next-community-docs.dev/docs/app-router/getting-started/ Next.js Document]&lt;br /&gt;
*[https://qiita.com/newbee1939/items/7ce919f9a1a7153582b8#:~:text=React%20Serv React Server ComponentsとApp Routerをそろそろちゃんと理解したい]&lt;br /&gt;
*Reactは、あくまでUI部分のみ&lt;br /&gt;
*本格的なアプリ開発には周辺領域を担うためのフレームワークが必要&lt;br /&gt;
*Reactベースのフレームワークとしてデファクトスタンダードと言える存在&lt;br /&gt;
*主なライブラリ&lt;br /&gt;
**ファイルシステムベースの設定レスルーター&lt;br /&gt;
**サーバーコンポーネント&lt;br /&gt;
**データ取得用fetchメソッド&lt;br /&gt;
**リソース組み込みの自動最適化&lt;br /&gt;
**CSSフレームワーク、Tailwind　CSSへの標準対応&lt;br /&gt;
&lt;br /&gt;
=導入=&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
newdelhi:Workspaces piroto$ npx create-next-app@latest&lt;br /&gt;
Need to install the following packages:&lt;br /&gt;
create-next-app@14.2.14&lt;br /&gt;
Ok to proceed? (y) y&lt;br /&gt;
&lt;br /&gt;
✔ What is your project named? … first-nextjs-app&lt;br /&gt;
✔ Would you like to use TypeScript? … No / Yes&lt;br /&gt;
✔ Would you like to use ESLint? … No / Yes&lt;br /&gt;
✔ Would you like to use Tailwind CSS? … No / Yes&lt;br /&gt;
✔ Would you like to use `src/` directory? … No / Yes&lt;br /&gt;
✔ Would you like to use App Router? (recommended) … No / Yes&lt;br /&gt;
✔ Would you like to customize the default import alias (@/*)? … No / Yes&lt;br /&gt;
Creating a new Next.js app in /Users/piroto/Workspaces/first-nextjs-app.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==実行==&lt;br /&gt;
===開発===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
npm run dev&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Start_next_js.png | 300px]]&lt;br /&gt;
&lt;br /&gt;
===本番ビルド＋実行===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
npm run build&lt;br /&gt;
npm start&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====ビルド結果がクリーンされない====&lt;br /&gt;
*https://blog.unimoku.com/20201209&lt;br /&gt;
*/.next /out はビルド時に削除しても良い。&lt;br /&gt;
*デフォルトでクリーンされない&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rm -rf .next out&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==App Router==&lt;br /&gt;
*React Routerとは異なる独自のルーターを標準で提供&lt;br /&gt;
*コンポーネントそのものはReactと変わらない&lt;br /&gt;
&lt;br /&gt;
===2種類のルーター===&lt;br /&gt;
&lt;br /&gt;
*Pages Router : 旧来から提供されている&lt;br /&gt;
*App Router : Next.js 13から導入された新しいルーター(推奨)&lt;br /&gt;
&lt;br /&gt;
====App Router====&lt;br /&gt;
*フォルダベースのルーター&lt;br /&gt;
*ルート定義不要、フォルダ階層に準じてリクエストパスとコンポーネント(.jsファイル)との対応関係が決まる&lt;br /&gt;
*page.jsはファイル名も固定でフォルダー構造だけでリクエストパスが決定される&lt;br /&gt;
*デフォルトで作成したコンポーネントがサーバーコンポーネントになる&lt;br /&gt;
*クライアントコンポーネントにするにはuse clientを記述する必要がある&lt;br /&gt;
&lt;br /&gt;
=====アプリ共通の外枠=====&lt;br /&gt;
*layout.js&lt;br /&gt;
*&amp;amp;lt;html&amp;amp;gt;、&amp;amp;lt;body&amp;amp;gt; 要素が存在し、個々のページを埋め込むため chilrenプロパティを引用していることが条件&lt;br /&gt;
&lt;br /&gt;
===ルートパラメータ===&lt;br /&gt;
*[名前] ： 単一パラメータ&lt;br /&gt;
*[...名前] : キャッチオールセグメント&lt;br /&gt;
*&amp;lt;nowiki&amp;gt;[[...名前]]&amp;lt;/nowiki&amp;gt; : 省略可能なキャッチオールセグメント&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ App Routerのルートパラメータ&lt;br /&gt;
|-&lt;br /&gt;
! フォルダ階層 !! 対応リクエスト !! パラメータ&lt;br /&gt;
|-&lt;br /&gt;
| /app/hoge/[id]/page.js || /hoge/001 || { id : '001' }&lt;br /&gt;
|-&lt;br /&gt;
| /app/foo/[...keys]/page.js || /foo/aaa/bbb || { keys: ['aaa', 'bbb'] }&lt;br /&gt;
|-&lt;br /&gt;
| /app/bar/&amp;lt;nowiki&amp;gt;[[...keys]]&amp;lt;/nowiki&amp;gt;/page.js || /bar || {}&lt;br /&gt;
|-&lt;br /&gt;
| 〃 || /bar/aaa/bbb || { keys: ['aaa', 'bbb'] }&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Tailwind CSS==&lt;br /&gt;
*https://tailwindcss.com/&lt;br /&gt;
*ユーティリティファーストをコンセプトに開発されたCSSフレームワーク&lt;br /&gt;
*ユーティリティを組み合わせてデザインを作るので独自のスタイルを作りやすく細かな調整もしやすいメリット&lt;br /&gt;
*標準のサイズ、カラーなどは用意されている&lt;br /&gt;
&lt;br /&gt;
[https://tailwindcsscheatsheet.com/ Cheat Sheet]&lt;br /&gt;
&lt;br /&gt;
*Tailwind　CSSによるスタイルを適用&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import &amp;quot;./globals.css&amp;quot;;&lt;br /&gt;
    :&lt;br /&gt;
&lt;br /&gt;
&amp;amp;lt;ul className=&amp;quot;fle bg-blue-600 mb-4 pl-2&amp;quot;&amp;amp;gt;...&amp;amp;lt;/ul&amp;amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Prisma==&lt;br /&gt;
*JavaScriptアプリからデータベース操作を取り持つO/Rマッパー&lt;br /&gt;
===インストール===&lt;br /&gt;
*成功すると以下のファイルが生成される&lt;br /&gt;
**.env : 環境変数ファイル、gitignore に追加する&lt;br /&gt;
** prisma/schema.prisma : Prismaのスキーマファイル&lt;br /&gt;
&lt;br /&gt;
sqliteでの構成例&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ npm install prisma --save-dev&lt;br /&gt;
 $ npx prisma init --datasource-provider sqlite&lt;br /&gt;
 warn You already have a .gitignore file. Don't forget to add `.env` in it to not commit any private information.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===データモデルの定義===&lt;br /&gt;
*prisma/schema.prisma に追記&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
model　reviews {&lt;br /&gt;
  id          String @id&lt;br /&gt;
  title       String&lt;br /&gt;
  author      String&lt;br /&gt;
  price       Int&lt;br /&gt;
  publlisher  String&lt;br /&gt;
  published   String&lt;br /&gt;
  image       String&lt;br /&gt;
  read        DateTime  @default(now())&lt;br /&gt;
  memo        String&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*DBに反映&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ npx prisma db push&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Prisma Studio(Webベース管理ツール)で確認&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ npx prisma studio&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Error: @prisma/client did not initialize yet. Please run &amp;quot;prisma generate&amp;quot; and try to import it again.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ nps prisma generate&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import { PrismaClient } from &amp;quot;@prisma/client&amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Prisma Clientの利用&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import { PrismaClient } from &amp;quot;@prisma/client&amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==サーバーアクション==&lt;br /&gt;
*Next.js内蔵の仕組み&lt;br /&gt;
*ページコンポーネント、イベントハンドラー、&amp;amp;lt;form&amp;amp;lt;要素のaction属性などからサーバーコードを呼び出す仕組み&lt;br /&gt;
*サーバーとのやりとりに際し、fetchなどの非同期通信コードの不要となり、例えばコンポーネントからデータベースを操作するにも直感的なコードを記述できる&lt;br /&gt;
*現時点ではα版&lt;br /&gt;
&lt;br /&gt;
===有効化===&lt;br /&gt;
&lt;br /&gt;
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]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
const nextConfig = {&lt;br /&gt;
    experimental: {&lt;br /&gt;
        serverActions: true&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=コンポーネントの処理=&lt;br /&gt;
*[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 サーバーとクライアントの構成パターン]&lt;br /&gt;
&lt;br /&gt;
==サーバー側で実行==&lt;br /&gt;
*Next.jsの基本はサーバー側でコンポーネントを処理&lt;br /&gt;
*[https://www.ey-office.com/blog_archive/2024/05/29/tried-running-react-server-component-in-a-production-environment-and-got-a-little-hooked/ 本番環境で動かす]&lt;br /&gt;
*メリット&lt;br /&gt;
**サーバーリソースの活用&lt;br /&gt;
**ダウンロードコードサイズの最小化&lt;br /&gt;
**機密情報(サクセストークンなど)の管理&lt;br /&gt;
*クライアントに依存する操作には対応していない&lt;br /&gt;
**State関連操作(useState,useReducer,useEffectなど)&lt;br /&gt;
**イベントリスナー(onXxxxx)&lt;br /&gt;
**ブラウザAPIアクセス&lt;br /&gt;
**上記を伴うカスタムフック&lt;br /&gt;
**クラスコンポーネント利用&lt;br /&gt;
&lt;br /&gt;
==クライアント側で実行==&lt;br /&gt;
*ファイルの先頭に、'use client'ディレクティブを記述することでコンポーネントをクライアント側で実行可&lt;br /&gt;
&lt;br /&gt;
==静的サイト==&lt;br /&gt;
*[https://zenn.dev/hiromu617/articles/1ed6811dc6cf26 静的サイトの生成]&lt;br /&gt;
*静的エクスポートを有効にすることによりビルド時の生成物がNode.jsサーバーを必要としないものとなる&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
const nextConfig = {&lt;br /&gt;
    :&lt;br /&gt;
    output: 'export'&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
*この機能を有効にすることで、ridirectsやmiddlewareなどのサーバーを必要とする一部機能が使えなくなります&lt;br /&gt;
*動的レンダリングも一切できなくなってしまうのでこの機能を有効にするかはアプリケーションの性質を考慮して検討&lt;br /&gt;
&lt;br /&gt;
=実装=&lt;br /&gt;
&lt;br /&gt;
==ルートレイアウト==&lt;br /&gt;
===アプリ内のリンクにはLinkコンポーネントを利用===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import Link from &amp;quot;next/link&amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
規定で以下のようなコンポーネントが用意されており、アプリ内リソースを効率的に利用できる&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ コンポーネント&lt;br /&gt;
|-&lt;br /&gt;
! コンポーネント !! 概要&lt;br /&gt;
|-&lt;br /&gt;
| &amp;amp;lt;Link&amp;amp;gt; || リンクを生成&lt;br /&gt;
|-&lt;br /&gt;
| &amp;amp;lt;Script&amp;amp;gt; || スクリプトのロード&lt;br /&gt;
|-&lt;br /&gt;
| &amp;amp;lt;Image&amp;amp;gt; || 画像を表示&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===メタデータ===&lt;br /&gt;
*メタデータを定義しておくことで、個々のページに適切なヘッダーなどを埋め込める&lt;br /&gt;
*複数箇所で宣言された場合、シャローマージされる&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
export const metadata: Metadata = {&lt;br /&gt;
  title: &amp;quot;Reading Recorder&amp;quot;,&lt;br /&gt;
  description: &amp;quot;自分が読んだ書籍の記録を残す&amp;quot;,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*generateMetadata関数を利用しデータベースなどから取得した結果を元に動的に生成も可能&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
export async function generateMetadata({ params, searchParams }) {&lt;br /&gt;
    :&lt;br /&gt;
    return {&lt;br /&gt;
        title : result.title,&lt;br /&gt;
            :&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Route Segment Config===&lt;br /&gt;
*https://nextjs.org/docs/app/api-reference/file-conventions/route-segment-config&lt;br /&gt;
*レイアウト、ページ単位の設定 &lt;br /&gt;
*あらかじめ決められた名前の変数をエクスポートしておくことで、個別の設定を施せる&lt;br /&gt;
*force-dynamic : 極力キャッシュを無効にし、ページを動的に描画しようとする&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
export const dynamic = 'force-dynamic'&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=フォント=&lt;br /&gt;
*Googleフォント(無償フォントのディレクトリサービス)を有効化&lt;br /&gt;
*具体的なフォントはGoogleフォントから自由に選択できるが一般的にはバリアブルフォント推奨(下例ではInconsolata)&lt;br /&gt;
*フォントはファイルサイズが大きいので、subsetで利用する文字のみ取り出す&lt;br /&gt;
*fnc.className でフォントを適用できる&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import { Inconsolata } from 'next/font/google';&lt;br /&gt;
const fnt = Inconsolata({ subsets: ['latin'] });&lt;br /&gt;
&lt;br /&gt;
  :&lt;br /&gt;
&amp;amp;lt;body className={`${fnt.className}` }&amp;amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=MUI=&lt;br /&gt;
[[MUI]]&lt;br /&gt;
&lt;br /&gt;
=Tips=&lt;br /&gt;
&lt;br /&gt;
==リモートホストからの画像表示を許可する==&lt;br /&gt;
*next.config.mjs&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
const nextConfig = {&lt;br /&gt;
&lt;br /&gt;
    :&lt;br /&gt;
&lt;br /&gt;
    images: {&lt;br /&gt;
        remotePatterns: [&lt;br /&gt;
            {&lt;br /&gt;
                hostname: 'books.google.com'&lt;br /&gt;
            } &lt;br /&gt;
        ] &lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Piroto</name></author>
		
	</entry>
	<entry>
		<id>https://www.typea.info/tips_/index.php?title=Next.js&amp;diff=35351</id>
		<title>Next.js</title>
		<link rel="alternate" type="text/html" href="https://www.typea.info/tips_/index.php?title=Next.js&amp;diff=35351"/>
		<updated>2024-10-05T16:17:21Z</updated>

		<summary type="html">&lt;p&gt;Piroto: /* Route Segment Config */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[React]] | [[MUI]] |&lt;br /&gt;
&lt;br /&gt;
{{amazon|4815619484}}&lt;br /&gt;
&lt;br /&gt;
=概要=&lt;br /&gt;
*[https://ja.next-community-docs.dev/docs/app-router/getting-started/ Next.js Document]&lt;br /&gt;
*[https://qiita.com/newbee1939/items/7ce919f9a1a7153582b8#:~:text=React%20Serv React Server ComponentsとApp Routerをそろそろちゃんと理解したい]&lt;br /&gt;
*Reactは、あくまでUI部分のみ&lt;br /&gt;
*本格的なアプリ開発には周辺領域を担うためのフレームワークが必要&lt;br /&gt;
*Reactベースのフレームワークとしてデファクトスタンダードと言える存在&lt;br /&gt;
*主なライブラリ&lt;br /&gt;
**ファイルシステムベースの設定レスルーター&lt;br /&gt;
**サーバーコンポーネント&lt;br /&gt;
**データ取得用fetchメソッド&lt;br /&gt;
**リソース組み込みの自動最適化&lt;br /&gt;
**CSSフレームワーク、Tailwind　CSSへの標準対応&lt;br /&gt;
&lt;br /&gt;
=導入=&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
newdelhi:Workspaces piroto$ npx create-next-app@latest&lt;br /&gt;
Need to install the following packages:&lt;br /&gt;
create-next-app@14.2.14&lt;br /&gt;
Ok to proceed? (y) y&lt;br /&gt;
&lt;br /&gt;
✔ What is your project named? … first-nextjs-app&lt;br /&gt;
✔ Would you like to use TypeScript? … No / Yes&lt;br /&gt;
✔ Would you like to use ESLint? … No / Yes&lt;br /&gt;
✔ Would you like to use Tailwind CSS? … No / Yes&lt;br /&gt;
✔ Would you like to use `src/` directory? … No / Yes&lt;br /&gt;
✔ Would you like to use App Router? (recommended) … No / Yes&lt;br /&gt;
✔ Would you like to customize the default import alias (@/*)? … No / Yes&lt;br /&gt;
Creating a new Next.js app in /Users/piroto/Workspaces/first-nextjs-app.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==実行==&lt;br /&gt;
===開発===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
npm run dev&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Start_next_js.png | 300px]]&lt;br /&gt;
&lt;br /&gt;
===本番ビルド＋実行===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
npm run build&lt;br /&gt;
npm start&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==App Router==&lt;br /&gt;
*React Routerとは異なる独自のルーターを標準で提供&lt;br /&gt;
*コンポーネントそのものはReactと変わらない&lt;br /&gt;
&lt;br /&gt;
===2種類のルーター===&lt;br /&gt;
&lt;br /&gt;
*Pages Router : 旧来から提供されている&lt;br /&gt;
*App Router : Next.js 13から導入された新しいルーター(推奨)&lt;br /&gt;
&lt;br /&gt;
====App Router====&lt;br /&gt;
*フォルダベースのルーター&lt;br /&gt;
*ルート定義不要、フォルダ階層に準じてリクエストパスとコンポーネント(.jsファイル)との対応関係が決まる&lt;br /&gt;
*page.jsはファイル名も固定でフォルダー構造だけでリクエストパスが決定される&lt;br /&gt;
*デフォルトで作成したコンポーネントがサーバーコンポーネントになる&lt;br /&gt;
*クライアントコンポーネントにするにはuse clientを記述する必要がある&lt;br /&gt;
&lt;br /&gt;
=====アプリ共通の外枠=====&lt;br /&gt;
*layout.js&lt;br /&gt;
*&amp;amp;lt;html&amp;amp;gt;、&amp;amp;lt;body&amp;amp;gt; 要素が存在し、個々のページを埋め込むため chilrenプロパティを引用していることが条件&lt;br /&gt;
&lt;br /&gt;
===ルートパラメータ===&lt;br /&gt;
*[名前] ： 単一パラメータ&lt;br /&gt;
*[...名前] : キャッチオールセグメント&lt;br /&gt;
*&amp;lt;nowiki&amp;gt;[[...名前]]&amp;lt;/nowiki&amp;gt; : 省略可能なキャッチオールセグメント&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ App Routerのルートパラメータ&lt;br /&gt;
|-&lt;br /&gt;
! フォルダ階層 !! 対応リクエスト !! パラメータ&lt;br /&gt;
|-&lt;br /&gt;
| /app/hoge/[id]/page.js || /hoge/001 || { id : '001' }&lt;br /&gt;
|-&lt;br /&gt;
| /app/foo/[...keys]/page.js || /foo/aaa/bbb || { keys: ['aaa', 'bbb'] }&lt;br /&gt;
|-&lt;br /&gt;
| /app/bar/&amp;lt;nowiki&amp;gt;[[...keys]]&amp;lt;/nowiki&amp;gt;/page.js || /bar || {}&lt;br /&gt;
|-&lt;br /&gt;
| 〃 || /bar/aaa/bbb || { keys: ['aaa', 'bbb'] }&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Tailwind CSS==&lt;br /&gt;
*https://tailwindcss.com/&lt;br /&gt;
*ユーティリティファーストをコンセプトに開発されたCSSフレームワーク&lt;br /&gt;
*ユーティリティを組み合わせてデザインを作るので独自のスタイルを作りやすく細かな調整もしやすいメリット&lt;br /&gt;
*標準のサイズ、カラーなどは用意されている&lt;br /&gt;
&lt;br /&gt;
[https://tailwindcsscheatsheet.com/ Cheat Sheet]&lt;br /&gt;
&lt;br /&gt;
*Tailwind　CSSによるスタイルを適用&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import &amp;quot;./globals.css&amp;quot;;&lt;br /&gt;
    :&lt;br /&gt;
&lt;br /&gt;
&amp;amp;lt;ul className=&amp;quot;fle bg-blue-600 mb-4 pl-2&amp;quot;&amp;amp;gt;...&amp;amp;lt;/ul&amp;amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Prisma==&lt;br /&gt;
*JavaScriptアプリからデータベース操作を取り持つO/Rマッパー&lt;br /&gt;
===インストール===&lt;br /&gt;
*成功すると以下のファイルが生成される&lt;br /&gt;
**.env : 環境変数ファイル、gitignore に追加する&lt;br /&gt;
** prisma/schema.prisma : Prismaのスキーマファイル&lt;br /&gt;
&lt;br /&gt;
sqliteでの構成例&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ npm install prisma --save-dev&lt;br /&gt;
 $ npx prisma init --datasource-provider sqlite&lt;br /&gt;
 warn You already have a .gitignore file. Don't forget to add `.env` in it to not commit any private information.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===データモデルの定義===&lt;br /&gt;
*prisma/schema.prisma に追記&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
model　reviews {&lt;br /&gt;
  id          String @id&lt;br /&gt;
  title       String&lt;br /&gt;
  author      String&lt;br /&gt;
  price       Int&lt;br /&gt;
  publlisher  String&lt;br /&gt;
  published   String&lt;br /&gt;
  image       String&lt;br /&gt;
  read        DateTime  @default(now())&lt;br /&gt;
  memo        String&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*DBに反映&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ npx prisma db push&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Prisma Studio(Webベース管理ツール)で確認&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ npx prisma studio&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Error: @prisma/client did not initialize yet. Please run &amp;quot;prisma generate&amp;quot; and try to import it again.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ nps prisma generate&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import { PrismaClient } from &amp;quot;@prisma/client&amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Prisma Clientの利用&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import { PrismaClient } from &amp;quot;@prisma/client&amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==サーバーアクション==&lt;br /&gt;
*Next.js内蔵の仕組み&lt;br /&gt;
*ページコンポーネント、イベントハンドラー、&amp;amp;lt;form&amp;amp;lt;要素のaction属性などからサーバーコードを呼び出す仕組み&lt;br /&gt;
*サーバーとのやりとりに際し、fetchなどの非同期通信コードの不要となり、例えばコンポーネントからデータベースを操作するにも直感的なコードを記述できる&lt;br /&gt;
*現時点ではα版&lt;br /&gt;
&lt;br /&gt;
===有効化===&lt;br /&gt;
&lt;br /&gt;
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]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
const nextConfig = {&lt;br /&gt;
    experimental: {&lt;br /&gt;
        serverActions: true&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=コンポーネントの処理=&lt;br /&gt;
*[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 サーバーとクライアントの構成パターン]&lt;br /&gt;
&lt;br /&gt;
==サーバー側で実行==&lt;br /&gt;
*Next.jsの基本はサーバー側でコンポーネントを処理&lt;br /&gt;
*[https://www.ey-office.com/blog_archive/2024/05/29/tried-running-react-server-component-in-a-production-environment-and-got-a-little-hooked/ 本番環境で動かす]&lt;br /&gt;
*メリット&lt;br /&gt;
**サーバーリソースの活用&lt;br /&gt;
**ダウンロードコードサイズの最小化&lt;br /&gt;
**機密情報(サクセストークンなど)の管理&lt;br /&gt;
*クライアントに依存する操作には対応していない&lt;br /&gt;
**State関連操作(useState,useReducer,useEffectなど)&lt;br /&gt;
**イベントリスナー(onXxxxx)&lt;br /&gt;
**ブラウザAPIアクセス&lt;br /&gt;
**上記を伴うカスタムフック&lt;br /&gt;
**クラスコンポーネント利用&lt;br /&gt;
&lt;br /&gt;
==クライアント側で実行==&lt;br /&gt;
*ファイルの先頭に、'use client'ディレクティブを記述することでコンポーネントをクライアント側で実行可&lt;br /&gt;
&lt;br /&gt;
==静的サイト==&lt;br /&gt;
*[https://zenn.dev/hiromu617/articles/1ed6811dc6cf26 静的サイトの生成]&lt;br /&gt;
*静的エクスポートを有効にすることによりビルド時の生成物がNode.jsサーバーを必要としないものとなる&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
const nextConfig = {&lt;br /&gt;
    :&lt;br /&gt;
    output: 'export'&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
*この機能を有効にすることで、ridirectsやmiddlewareなどのサーバーを必要とする一部機能が使えなくなります&lt;br /&gt;
*動的レンダリングも一切できなくなってしまうのでこの機能を有効にするかはアプリケーションの性質を考慮して検討&lt;br /&gt;
&lt;br /&gt;
=実装=&lt;br /&gt;
&lt;br /&gt;
==ルートレイアウト==&lt;br /&gt;
===アプリ内のリンクにはLinkコンポーネントを利用===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import Link from &amp;quot;next/link&amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
規定で以下のようなコンポーネントが用意されており、アプリ内リソースを効率的に利用できる&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ コンポーネント&lt;br /&gt;
|-&lt;br /&gt;
! コンポーネント !! 概要&lt;br /&gt;
|-&lt;br /&gt;
| &amp;amp;lt;Link&amp;amp;gt; || リンクを生成&lt;br /&gt;
|-&lt;br /&gt;
| &amp;amp;lt;Script&amp;amp;gt; || スクリプトのロード&lt;br /&gt;
|-&lt;br /&gt;
| &amp;amp;lt;Image&amp;amp;gt; || 画像を表示&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===メタデータ===&lt;br /&gt;
*メタデータを定義しておくことで、個々のページに適切なヘッダーなどを埋め込める&lt;br /&gt;
*複数箇所で宣言された場合、シャローマージされる&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
export const metadata: Metadata = {&lt;br /&gt;
  title: &amp;quot;Reading Recorder&amp;quot;,&lt;br /&gt;
  description: &amp;quot;自分が読んだ書籍の記録を残す&amp;quot;,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*generateMetadata関数を利用しデータベースなどから取得した結果を元に動的に生成も可能&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
export async function generateMetadata({ params, searchParams }) {&lt;br /&gt;
    :&lt;br /&gt;
    return {&lt;br /&gt;
        title : result.title,&lt;br /&gt;
            :&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Route Segment Config===&lt;br /&gt;
*https://nextjs.org/docs/app/api-reference/file-conventions/route-segment-config&lt;br /&gt;
*レイアウト、ページ単位の設定 &lt;br /&gt;
*あらかじめ決められた名前の変数をエクスポートしておくことで、個別の設定を施せる&lt;br /&gt;
*force-dynamic : 極力キャッシュを無効にし、ページを動的に描画しようとする&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
export const dynamic = 'force-dynamic'&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=フォント=&lt;br /&gt;
*Googleフォント(無償フォントのディレクトリサービス)を有効化&lt;br /&gt;
*具体的なフォントはGoogleフォントから自由に選択できるが一般的にはバリアブルフォント推奨(下例ではInconsolata)&lt;br /&gt;
*フォントはファイルサイズが大きいので、subsetで利用する文字のみ取り出す&lt;br /&gt;
*fnc.className でフォントを適用できる&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import { Inconsolata } from 'next/font/google';&lt;br /&gt;
const fnt = Inconsolata({ subsets: ['latin'] });&lt;br /&gt;
&lt;br /&gt;
  :&lt;br /&gt;
&amp;amp;lt;body className={`${fnt.className}` }&amp;amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=MUI=&lt;br /&gt;
[[MUI]]&lt;br /&gt;
&lt;br /&gt;
=Tips=&lt;br /&gt;
&lt;br /&gt;
==リモートホストからの画像表示を許可する==&lt;br /&gt;
*next.config.mjs&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
const nextConfig = {&lt;br /&gt;
&lt;br /&gt;
    :&lt;br /&gt;
&lt;br /&gt;
    images: {&lt;br /&gt;
        remotePatterns: [&lt;br /&gt;
            {&lt;br /&gt;
                hostname: 'books.google.com'&lt;br /&gt;
            } &lt;br /&gt;
        ] &lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Piroto</name></author>
		
	</entry>
	<entry>
		<id>https://www.typea.info/tips_/index.php?title=Next.js&amp;diff=35350</id>
		<title>Next.js</title>
		<link rel="alternate" type="text/html" href="https://www.typea.info/tips_/index.php?title=Next.js&amp;diff=35350"/>
		<updated>2024-10-05T16:17:03Z</updated>

		<summary type="html">&lt;p&gt;Piroto: /* コンポーネントの処理 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[React]] | [[MUI]] |&lt;br /&gt;
&lt;br /&gt;
{{amazon|4815619484}}&lt;br /&gt;
&lt;br /&gt;
=概要=&lt;br /&gt;
*[https://ja.next-community-docs.dev/docs/app-router/getting-started/ Next.js Document]&lt;br /&gt;
*[https://qiita.com/newbee1939/items/7ce919f9a1a7153582b8#:~:text=React%20Serv React Server ComponentsとApp Routerをそろそろちゃんと理解したい]&lt;br /&gt;
*Reactは、あくまでUI部分のみ&lt;br /&gt;
*本格的なアプリ開発には周辺領域を担うためのフレームワークが必要&lt;br /&gt;
*Reactベースのフレームワークとしてデファクトスタンダードと言える存在&lt;br /&gt;
*主なライブラリ&lt;br /&gt;
**ファイルシステムベースの設定レスルーター&lt;br /&gt;
**サーバーコンポーネント&lt;br /&gt;
**データ取得用fetchメソッド&lt;br /&gt;
**リソース組み込みの自動最適化&lt;br /&gt;
**CSSフレームワーク、Tailwind　CSSへの標準対応&lt;br /&gt;
&lt;br /&gt;
=導入=&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
newdelhi:Workspaces piroto$ npx create-next-app@latest&lt;br /&gt;
Need to install the following packages:&lt;br /&gt;
create-next-app@14.2.14&lt;br /&gt;
Ok to proceed? (y) y&lt;br /&gt;
&lt;br /&gt;
✔ What is your project named? … first-nextjs-app&lt;br /&gt;
✔ Would you like to use TypeScript? … No / Yes&lt;br /&gt;
✔ Would you like to use ESLint? … No / Yes&lt;br /&gt;
✔ Would you like to use Tailwind CSS? … No / Yes&lt;br /&gt;
✔ Would you like to use `src/` directory? … No / Yes&lt;br /&gt;
✔ Would you like to use App Router? (recommended) … No / Yes&lt;br /&gt;
✔ Would you like to customize the default import alias (@/*)? … No / Yes&lt;br /&gt;
Creating a new Next.js app in /Users/piroto/Workspaces/first-nextjs-app.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==実行==&lt;br /&gt;
===開発===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
npm run dev&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Start_next_js.png | 300px]]&lt;br /&gt;
&lt;br /&gt;
===本番ビルド＋実行===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
npm run build&lt;br /&gt;
npm start&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==App Router==&lt;br /&gt;
*React Routerとは異なる独自のルーターを標準で提供&lt;br /&gt;
*コンポーネントそのものはReactと変わらない&lt;br /&gt;
&lt;br /&gt;
===2種類のルーター===&lt;br /&gt;
&lt;br /&gt;
*Pages Router : 旧来から提供されている&lt;br /&gt;
*App Router : Next.js 13から導入された新しいルーター(推奨)&lt;br /&gt;
&lt;br /&gt;
====App Router====&lt;br /&gt;
*フォルダベースのルーター&lt;br /&gt;
*ルート定義不要、フォルダ階層に準じてリクエストパスとコンポーネント(.jsファイル)との対応関係が決まる&lt;br /&gt;
*page.jsはファイル名も固定でフォルダー構造だけでリクエストパスが決定される&lt;br /&gt;
*デフォルトで作成したコンポーネントがサーバーコンポーネントになる&lt;br /&gt;
*クライアントコンポーネントにするにはuse clientを記述する必要がある&lt;br /&gt;
&lt;br /&gt;
=====アプリ共通の外枠=====&lt;br /&gt;
*layout.js&lt;br /&gt;
*&amp;amp;lt;html&amp;amp;gt;、&amp;amp;lt;body&amp;amp;gt; 要素が存在し、個々のページを埋め込むため chilrenプロパティを引用していることが条件&lt;br /&gt;
&lt;br /&gt;
===ルートパラメータ===&lt;br /&gt;
*[名前] ： 単一パラメータ&lt;br /&gt;
*[...名前] : キャッチオールセグメント&lt;br /&gt;
*&amp;lt;nowiki&amp;gt;[[...名前]]&amp;lt;/nowiki&amp;gt; : 省略可能なキャッチオールセグメント&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ App Routerのルートパラメータ&lt;br /&gt;
|-&lt;br /&gt;
! フォルダ階層 !! 対応リクエスト !! パラメータ&lt;br /&gt;
|-&lt;br /&gt;
| /app/hoge/[id]/page.js || /hoge/001 || { id : '001' }&lt;br /&gt;
|-&lt;br /&gt;
| /app/foo/[...keys]/page.js || /foo/aaa/bbb || { keys: ['aaa', 'bbb'] }&lt;br /&gt;
|-&lt;br /&gt;
| /app/bar/&amp;lt;nowiki&amp;gt;[[...keys]]&amp;lt;/nowiki&amp;gt;/page.js || /bar || {}&lt;br /&gt;
|-&lt;br /&gt;
| 〃 || /bar/aaa/bbb || { keys: ['aaa', 'bbb'] }&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Tailwind CSS==&lt;br /&gt;
*https://tailwindcss.com/&lt;br /&gt;
*ユーティリティファーストをコンセプトに開発されたCSSフレームワーク&lt;br /&gt;
*ユーティリティを組み合わせてデザインを作るので独自のスタイルを作りやすく細かな調整もしやすいメリット&lt;br /&gt;
*標準のサイズ、カラーなどは用意されている&lt;br /&gt;
&lt;br /&gt;
[https://tailwindcsscheatsheet.com/ Cheat Sheet]&lt;br /&gt;
&lt;br /&gt;
*Tailwind　CSSによるスタイルを適用&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import &amp;quot;./globals.css&amp;quot;;&lt;br /&gt;
    :&lt;br /&gt;
&lt;br /&gt;
&amp;amp;lt;ul className=&amp;quot;fle bg-blue-600 mb-4 pl-2&amp;quot;&amp;amp;gt;...&amp;amp;lt;/ul&amp;amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Prisma==&lt;br /&gt;
*JavaScriptアプリからデータベース操作を取り持つO/Rマッパー&lt;br /&gt;
===インストール===&lt;br /&gt;
*成功すると以下のファイルが生成される&lt;br /&gt;
**.env : 環境変数ファイル、gitignore に追加する&lt;br /&gt;
** prisma/schema.prisma : Prismaのスキーマファイル&lt;br /&gt;
&lt;br /&gt;
sqliteでの構成例&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ npm install prisma --save-dev&lt;br /&gt;
 $ npx prisma init --datasource-provider sqlite&lt;br /&gt;
 warn You already have a .gitignore file. Don't forget to add `.env` in it to not commit any private information.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===データモデルの定義===&lt;br /&gt;
*prisma/schema.prisma に追記&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
model　reviews {&lt;br /&gt;
  id          String @id&lt;br /&gt;
  title       String&lt;br /&gt;
  author      String&lt;br /&gt;
  price       Int&lt;br /&gt;
  publlisher  String&lt;br /&gt;
  published   String&lt;br /&gt;
  image       String&lt;br /&gt;
  read        DateTime  @default(now())&lt;br /&gt;
  memo        String&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*DBに反映&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ npx prisma db push&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Prisma Studio(Webベース管理ツール)で確認&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ npx prisma studio&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Error: @prisma/client did not initialize yet. Please run &amp;quot;prisma generate&amp;quot; and try to import it again.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ nps prisma generate&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import { PrismaClient } from &amp;quot;@prisma/client&amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Prisma Clientの利用&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import { PrismaClient } from &amp;quot;@prisma/client&amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==サーバーアクション==&lt;br /&gt;
*Next.js内蔵の仕組み&lt;br /&gt;
*ページコンポーネント、イベントハンドラー、&amp;amp;lt;form&amp;amp;lt;要素のaction属性などからサーバーコードを呼び出す仕組み&lt;br /&gt;
*サーバーとのやりとりに際し、fetchなどの非同期通信コードの不要となり、例えばコンポーネントからデータベースを操作するにも直感的なコードを記述できる&lt;br /&gt;
*現時点ではα版&lt;br /&gt;
&lt;br /&gt;
===有効化===&lt;br /&gt;
&lt;br /&gt;
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]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
const nextConfig = {&lt;br /&gt;
    experimental: {&lt;br /&gt;
        serverActions: true&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=コンポーネントの処理=&lt;br /&gt;
*[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 サーバーとクライアントの構成パターン]&lt;br /&gt;
&lt;br /&gt;
==サーバー側で実行==&lt;br /&gt;
*Next.jsの基本はサーバー側でコンポーネントを処理&lt;br /&gt;
*[https://www.ey-office.com/blog_archive/2024/05/29/tried-running-react-server-component-in-a-production-environment-and-got-a-little-hooked/ 本番環境で動かす]&lt;br /&gt;
*メリット&lt;br /&gt;
**サーバーリソースの活用&lt;br /&gt;
**ダウンロードコードサイズの最小化&lt;br /&gt;
**機密情報(サクセストークンなど)の管理&lt;br /&gt;
*クライアントに依存する操作には対応していない&lt;br /&gt;
**State関連操作(useState,useReducer,useEffectなど)&lt;br /&gt;
**イベントリスナー(onXxxxx)&lt;br /&gt;
**ブラウザAPIアクセス&lt;br /&gt;
**上記を伴うカスタムフック&lt;br /&gt;
**クラスコンポーネント利用&lt;br /&gt;
&lt;br /&gt;
==クライアント側で実行==&lt;br /&gt;
*ファイルの先頭に、'use client'ディレクティブを記述することでコンポーネントをクライアント側で実行可&lt;br /&gt;
&lt;br /&gt;
==静的サイト==&lt;br /&gt;
*[https://zenn.dev/hiromu617/articles/1ed6811dc6cf26 静的サイトの生成]&lt;br /&gt;
*静的エクスポートを有効にすることによりビルド時の生成物がNode.jsサーバーを必要としないものとなる&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
const nextConfig = {&lt;br /&gt;
    :&lt;br /&gt;
    output: 'export'&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
*この機能を有効にすることで、ridirectsやmiddlewareなどのサーバーを必要とする一部機能が使えなくなります&lt;br /&gt;
*動的レンダリングも一切できなくなってしまうのでこの機能を有効にするかはアプリケーションの性質を考慮して検討&lt;br /&gt;
&lt;br /&gt;
=実装=&lt;br /&gt;
&lt;br /&gt;
==ルートレイアウト==&lt;br /&gt;
===アプリ内のリンクにはLinkコンポーネントを利用===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import Link from &amp;quot;next/link&amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
規定で以下のようなコンポーネントが用意されており、アプリ内リソースを効率的に利用できる&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ コンポーネント&lt;br /&gt;
|-&lt;br /&gt;
! コンポーネント !! 概要&lt;br /&gt;
|-&lt;br /&gt;
| &amp;amp;lt;Link&amp;amp;gt; || リンクを生成&lt;br /&gt;
|-&lt;br /&gt;
| &amp;amp;lt;Script&amp;amp;gt; || スクリプトのロード&lt;br /&gt;
|-&lt;br /&gt;
| &amp;amp;lt;Image&amp;amp;gt; || 画像を表示&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===メタデータ===&lt;br /&gt;
*メタデータを定義しておくことで、個々のページに適切なヘッダーなどを埋め込める&lt;br /&gt;
*複数箇所で宣言された場合、シャローマージされる&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
export const metadata: Metadata = {&lt;br /&gt;
  title: &amp;quot;Reading Recorder&amp;quot;,&lt;br /&gt;
  description: &amp;quot;自分が読んだ書籍の記録を残す&amp;quot;,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*generateMetadata関数を利用しデータベースなどから取得した結果を元に動的に生成も可能&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
export async function generateMetadata({ params, searchParams }) {&lt;br /&gt;
    :&lt;br /&gt;
    return {&lt;br /&gt;
        title : result.title,&lt;br /&gt;
            :&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Route Segment Config===&lt;br /&gt;
*レイアウト、ページ単位の設定 &lt;br /&gt;
*あらかじめ決められた名前の変数をエクスポートしておくことで、個別の設定を施せる&lt;br /&gt;
*force-dynamic : 極力キャッシュを無効にし、ページを動的に描画しようとする&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
export const dynamic = 'force-dynamic'&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=フォント=&lt;br /&gt;
*Googleフォント(無償フォントのディレクトリサービス)を有効化&lt;br /&gt;
*具体的なフォントはGoogleフォントから自由に選択できるが一般的にはバリアブルフォント推奨(下例ではInconsolata)&lt;br /&gt;
*フォントはファイルサイズが大きいので、subsetで利用する文字のみ取り出す&lt;br /&gt;
*fnc.className でフォントを適用できる&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import { Inconsolata } from 'next/font/google';&lt;br /&gt;
const fnt = Inconsolata({ subsets: ['latin'] });&lt;br /&gt;
&lt;br /&gt;
  :&lt;br /&gt;
&amp;amp;lt;body className={`${fnt.className}` }&amp;amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=MUI=&lt;br /&gt;
[[MUI]]&lt;br /&gt;
&lt;br /&gt;
=Tips=&lt;br /&gt;
&lt;br /&gt;
==リモートホストからの画像表示を許可する==&lt;br /&gt;
*next.config.mjs&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
const nextConfig = {&lt;br /&gt;
&lt;br /&gt;
    :&lt;br /&gt;
&lt;br /&gt;
    images: {&lt;br /&gt;
        remotePatterns: [&lt;br /&gt;
            {&lt;br /&gt;
                hostname: 'books.google.com'&lt;br /&gt;
            } &lt;br /&gt;
        ] &lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Piroto</name></author>
		
	</entry>
	<entry>
		<id>https://www.typea.info/tips_/index.php?title=Next.js&amp;diff=35349</id>
		<title>Next.js</title>
		<link rel="alternate" type="text/html" href="https://www.typea.info/tips_/index.php?title=Next.js&amp;diff=35349"/>
		<updated>2024-10-05T16:06:48Z</updated>

		<summary type="html">&lt;p&gt;Piroto: /* サーバー側で実行 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[React]] | [[MUI]] |&lt;br /&gt;
&lt;br /&gt;
{{amazon|4815619484}}&lt;br /&gt;
&lt;br /&gt;
=概要=&lt;br /&gt;
*[https://ja.next-community-docs.dev/docs/app-router/getting-started/ Next.js Document]&lt;br /&gt;
*[https://qiita.com/newbee1939/items/7ce919f9a1a7153582b8#:~:text=React%20Serv React Server ComponentsとApp Routerをそろそろちゃんと理解したい]&lt;br /&gt;
*Reactは、あくまでUI部分のみ&lt;br /&gt;
*本格的なアプリ開発には周辺領域を担うためのフレームワークが必要&lt;br /&gt;
*Reactベースのフレームワークとしてデファクトスタンダードと言える存在&lt;br /&gt;
*主なライブラリ&lt;br /&gt;
**ファイルシステムベースの設定レスルーター&lt;br /&gt;
**サーバーコンポーネント&lt;br /&gt;
**データ取得用fetchメソッド&lt;br /&gt;
**リソース組み込みの自動最適化&lt;br /&gt;
**CSSフレームワーク、Tailwind　CSSへの標準対応&lt;br /&gt;
&lt;br /&gt;
=導入=&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
newdelhi:Workspaces piroto$ npx create-next-app@latest&lt;br /&gt;
Need to install the following packages:&lt;br /&gt;
create-next-app@14.2.14&lt;br /&gt;
Ok to proceed? (y) y&lt;br /&gt;
&lt;br /&gt;
✔ What is your project named? … first-nextjs-app&lt;br /&gt;
✔ Would you like to use TypeScript? … No / Yes&lt;br /&gt;
✔ Would you like to use ESLint? … No / Yes&lt;br /&gt;
✔ Would you like to use Tailwind CSS? … No / Yes&lt;br /&gt;
✔ Would you like to use `src/` directory? … No / Yes&lt;br /&gt;
✔ Would you like to use App Router? (recommended) … No / Yes&lt;br /&gt;
✔ Would you like to customize the default import alias (@/*)? … No / Yes&lt;br /&gt;
Creating a new Next.js app in /Users/piroto/Workspaces/first-nextjs-app.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==実行==&lt;br /&gt;
===開発===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
npm run dev&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Start_next_js.png | 300px]]&lt;br /&gt;
&lt;br /&gt;
===本番ビルド＋実行===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
npm run build&lt;br /&gt;
npm start&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==App Router==&lt;br /&gt;
*React Routerとは異なる独自のルーターを標準で提供&lt;br /&gt;
*コンポーネントそのものはReactと変わらない&lt;br /&gt;
&lt;br /&gt;
===2種類のルーター===&lt;br /&gt;
&lt;br /&gt;
*Pages Router : 旧来から提供されている&lt;br /&gt;
*App Router : Next.js 13から導入された新しいルーター(推奨)&lt;br /&gt;
&lt;br /&gt;
====App Router====&lt;br /&gt;
*フォルダベースのルーター&lt;br /&gt;
*ルート定義不要、フォルダ階層に準じてリクエストパスとコンポーネント(.jsファイル)との対応関係が決まる&lt;br /&gt;
*page.jsはファイル名も固定でフォルダー構造だけでリクエストパスが決定される&lt;br /&gt;
*デフォルトで作成したコンポーネントがサーバーコンポーネントになる&lt;br /&gt;
*クライアントコンポーネントにするにはuse clientを記述する必要がある&lt;br /&gt;
&lt;br /&gt;
=====アプリ共通の外枠=====&lt;br /&gt;
*layout.js&lt;br /&gt;
*&amp;amp;lt;html&amp;amp;gt;、&amp;amp;lt;body&amp;amp;gt; 要素が存在し、個々のページを埋め込むため chilrenプロパティを引用していることが条件&lt;br /&gt;
&lt;br /&gt;
===ルートパラメータ===&lt;br /&gt;
*[名前] ： 単一パラメータ&lt;br /&gt;
*[...名前] : キャッチオールセグメント&lt;br /&gt;
*&amp;lt;nowiki&amp;gt;[[...名前]]&amp;lt;/nowiki&amp;gt; : 省略可能なキャッチオールセグメント&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ App Routerのルートパラメータ&lt;br /&gt;
|-&lt;br /&gt;
! フォルダ階層 !! 対応リクエスト !! パラメータ&lt;br /&gt;
|-&lt;br /&gt;
| /app/hoge/[id]/page.js || /hoge/001 || { id : '001' }&lt;br /&gt;
|-&lt;br /&gt;
| /app/foo/[...keys]/page.js || /foo/aaa/bbb || { keys: ['aaa', 'bbb'] }&lt;br /&gt;
|-&lt;br /&gt;
| /app/bar/&amp;lt;nowiki&amp;gt;[[...keys]]&amp;lt;/nowiki&amp;gt;/page.js || /bar || {}&lt;br /&gt;
|-&lt;br /&gt;
| 〃 || /bar/aaa/bbb || { keys: ['aaa', 'bbb'] }&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Tailwind CSS==&lt;br /&gt;
*https://tailwindcss.com/&lt;br /&gt;
*ユーティリティファーストをコンセプトに開発されたCSSフレームワーク&lt;br /&gt;
*ユーティリティを組み合わせてデザインを作るので独自のスタイルを作りやすく細かな調整もしやすいメリット&lt;br /&gt;
*標準のサイズ、カラーなどは用意されている&lt;br /&gt;
&lt;br /&gt;
[https://tailwindcsscheatsheet.com/ Cheat Sheet]&lt;br /&gt;
&lt;br /&gt;
*Tailwind　CSSによるスタイルを適用&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import &amp;quot;./globals.css&amp;quot;;&lt;br /&gt;
    :&lt;br /&gt;
&lt;br /&gt;
&amp;amp;lt;ul className=&amp;quot;fle bg-blue-600 mb-4 pl-2&amp;quot;&amp;amp;gt;...&amp;amp;lt;/ul&amp;amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Prisma==&lt;br /&gt;
*JavaScriptアプリからデータベース操作を取り持つO/Rマッパー&lt;br /&gt;
===インストール===&lt;br /&gt;
*成功すると以下のファイルが生成される&lt;br /&gt;
**.env : 環境変数ファイル、gitignore に追加する&lt;br /&gt;
** prisma/schema.prisma : Prismaのスキーマファイル&lt;br /&gt;
&lt;br /&gt;
sqliteでの構成例&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ npm install prisma --save-dev&lt;br /&gt;
 $ npx prisma init --datasource-provider sqlite&lt;br /&gt;
 warn You already have a .gitignore file. Don't forget to add `.env` in it to not commit any private information.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===データモデルの定義===&lt;br /&gt;
*prisma/schema.prisma に追記&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
model　reviews {&lt;br /&gt;
  id          String @id&lt;br /&gt;
  title       String&lt;br /&gt;
  author      String&lt;br /&gt;
  price       Int&lt;br /&gt;
  publlisher  String&lt;br /&gt;
  published   String&lt;br /&gt;
  image       String&lt;br /&gt;
  read        DateTime  @default(now())&lt;br /&gt;
  memo        String&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*DBに反映&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ npx prisma db push&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Prisma Studio(Webベース管理ツール)で確認&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ npx prisma studio&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Error: @prisma/client did not initialize yet. Please run &amp;quot;prisma generate&amp;quot; and try to import it again.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ nps prisma generate&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import { PrismaClient } from &amp;quot;@prisma/client&amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Prisma Clientの利用&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import { PrismaClient } from &amp;quot;@prisma/client&amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==サーバーアクション==&lt;br /&gt;
*Next.js内蔵の仕組み&lt;br /&gt;
*ページコンポーネント、イベントハンドラー、&amp;amp;lt;form&amp;amp;lt;要素のaction属性などからサーバーコードを呼び出す仕組み&lt;br /&gt;
*サーバーとのやりとりに際し、fetchなどの非同期通信コードの不要となり、例えばコンポーネントからデータベースを操作するにも直感的なコードを記述できる&lt;br /&gt;
*現時点ではα版&lt;br /&gt;
&lt;br /&gt;
===有効化===&lt;br /&gt;
&lt;br /&gt;
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]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
const nextConfig = {&lt;br /&gt;
    experimental: {&lt;br /&gt;
        serverActions: true&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=コンポーネントの処理=&lt;br /&gt;
*[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 サーバーとクライアントの構成パターン]&lt;br /&gt;
&lt;br /&gt;
==サーバー側で実行==&lt;br /&gt;
*Next.jsの基本はサーバー側でコンポーネントを処理&lt;br /&gt;
*[https://www.ey-office.com/blog_archive/2024/05/29/tried-running-react-server-component-in-a-production-environment-and-got-a-little-hooked/ 本番環境で動かす]&lt;br /&gt;
*メリット&lt;br /&gt;
**サーバーリソースの活用&lt;br /&gt;
**ダウンロードコードサイズの最小化&lt;br /&gt;
**機密情報(サクセストークンなど)の管理&lt;br /&gt;
*クライアントに依存する操作には対応していない&lt;br /&gt;
**State関連操作(useState,useReducer,useEffectなど)&lt;br /&gt;
**イベントリスナー(onXxxxx)&lt;br /&gt;
**ブラウザAPIアクセス&lt;br /&gt;
**上記を伴うカスタムフック&lt;br /&gt;
**クラスコンポーネント利用&lt;br /&gt;
&lt;br /&gt;
==クライアント側で実行==&lt;br /&gt;
*ファイルの先頭に、'use client'ディレクティブを記述することでコンポーネントをクライアント側で実行可&lt;br /&gt;
&lt;br /&gt;
=実装=&lt;br /&gt;
&lt;br /&gt;
==ルートレイアウト==&lt;br /&gt;
===アプリ内のリンクにはLinkコンポーネントを利用===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import Link from &amp;quot;next/link&amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
規定で以下のようなコンポーネントが用意されており、アプリ内リソースを効率的に利用できる&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ コンポーネント&lt;br /&gt;
|-&lt;br /&gt;
! コンポーネント !! 概要&lt;br /&gt;
|-&lt;br /&gt;
| &amp;amp;lt;Link&amp;amp;gt; || リンクを生成&lt;br /&gt;
|-&lt;br /&gt;
| &amp;amp;lt;Script&amp;amp;gt; || スクリプトのロード&lt;br /&gt;
|-&lt;br /&gt;
| &amp;amp;lt;Image&amp;amp;gt; || 画像を表示&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===メタデータ===&lt;br /&gt;
*メタデータを定義しておくことで、個々のページに適切なヘッダーなどを埋め込める&lt;br /&gt;
*複数箇所で宣言された場合、シャローマージされる&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
export const metadata: Metadata = {&lt;br /&gt;
  title: &amp;quot;Reading Recorder&amp;quot;,&lt;br /&gt;
  description: &amp;quot;自分が読んだ書籍の記録を残す&amp;quot;,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*generateMetadata関数を利用しデータベースなどから取得した結果を元に動的に生成も可能&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
export async function generateMetadata({ params, searchParams }) {&lt;br /&gt;
    :&lt;br /&gt;
    return {&lt;br /&gt;
        title : result.title,&lt;br /&gt;
            :&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Route Segment Config===&lt;br /&gt;
*レイアウト、ページ単位の設定 &lt;br /&gt;
*あらかじめ決められた名前の変数をエクスポートしておくことで、個別の設定を施せる&lt;br /&gt;
*force-dynamic : 極力キャッシュを無効にし、ページを動的に描画しようとする&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
export const dynamic = 'force-dynamic'&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=フォント=&lt;br /&gt;
*Googleフォント(無償フォントのディレクトリサービス)を有効化&lt;br /&gt;
*具体的なフォントはGoogleフォントから自由に選択できるが一般的にはバリアブルフォント推奨(下例ではInconsolata)&lt;br /&gt;
*フォントはファイルサイズが大きいので、subsetで利用する文字のみ取り出す&lt;br /&gt;
*fnc.className でフォントを適用できる&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import { Inconsolata } from 'next/font/google';&lt;br /&gt;
const fnt = Inconsolata({ subsets: ['latin'] });&lt;br /&gt;
&lt;br /&gt;
  :&lt;br /&gt;
&amp;amp;lt;body className={`${fnt.className}` }&amp;amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=MUI=&lt;br /&gt;
[[MUI]]&lt;br /&gt;
&lt;br /&gt;
=Tips=&lt;br /&gt;
&lt;br /&gt;
==リモートホストからの画像表示を許可する==&lt;br /&gt;
*next.config.mjs&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
const nextConfig = {&lt;br /&gt;
&lt;br /&gt;
    :&lt;br /&gt;
&lt;br /&gt;
    images: {&lt;br /&gt;
        remotePatterns: [&lt;br /&gt;
            {&lt;br /&gt;
                hostname: 'books.google.com'&lt;br /&gt;
            } &lt;br /&gt;
        ] &lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Piroto</name></author>
		
	</entry>
	<entry>
		<id>https://www.typea.info/tips_/index.php?title=Next.js&amp;diff=35348</id>
		<title>Next.js</title>
		<link rel="alternate" type="text/html" href="https://www.typea.info/tips_/index.php?title=Next.js&amp;diff=35348"/>
		<updated>2024-10-05T15:51:50Z</updated>

		<summary type="html">&lt;p&gt;Piroto: /* 概要 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[React]] | [[MUI]] |&lt;br /&gt;
&lt;br /&gt;
{{amazon|4815619484}}&lt;br /&gt;
&lt;br /&gt;
=概要=&lt;br /&gt;
*[https://ja.next-community-docs.dev/docs/app-router/getting-started/ Next.js Document]&lt;br /&gt;
*[https://qiita.com/newbee1939/items/7ce919f9a1a7153582b8#:~:text=React%20Serv React Server ComponentsとApp Routerをそろそろちゃんと理解したい]&lt;br /&gt;
*Reactは、あくまでUI部分のみ&lt;br /&gt;
*本格的なアプリ開発には周辺領域を担うためのフレームワークが必要&lt;br /&gt;
*Reactベースのフレームワークとしてデファクトスタンダードと言える存在&lt;br /&gt;
*主なライブラリ&lt;br /&gt;
**ファイルシステムベースの設定レスルーター&lt;br /&gt;
**サーバーコンポーネント&lt;br /&gt;
**データ取得用fetchメソッド&lt;br /&gt;
**リソース組み込みの自動最適化&lt;br /&gt;
**CSSフレームワーク、Tailwind　CSSへの標準対応&lt;br /&gt;
&lt;br /&gt;
=導入=&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
newdelhi:Workspaces piroto$ npx create-next-app@latest&lt;br /&gt;
Need to install the following packages:&lt;br /&gt;
create-next-app@14.2.14&lt;br /&gt;
Ok to proceed? (y) y&lt;br /&gt;
&lt;br /&gt;
✔ What is your project named? … first-nextjs-app&lt;br /&gt;
✔ Would you like to use TypeScript? … No / Yes&lt;br /&gt;
✔ Would you like to use ESLint? … No / Yes&lt;br /&gt;
✔ Would you like to use Tailwind CSS? … No / Yes&lt;br /&gt;
✔ Would you like to use `src/` directory? … No / Yes&lt;br /&gt;
✔ Would you like to use App Router? (recommended) … No / Yes&lt;br /&gt;
✔ Would you like to customize the default import alias (@/*)? … No / Yes&lt;br /&gt;
Creating a new Next.js app in /Users/piroto/Workspaces/first-nextjs-app.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==実行==&lt;br /&gt;
===開発===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
npm run dev&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Start_next_js.png | 300px]]&lt;br /&gt;
&lt;br /&gt;
===本番ビルド＋実行===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
npm run build&lt;br /&gt;
npm start&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==App Router==&lt;br /&gt;
*React Routerとは異なる独自のルーターを標準で提供&lt;br /&gt;
*コンポーネントそのものはReactと変わらない&lt;br /&gt;
&lt;br /&gt;
===2種類のルーター===&lt;br /&gt;
&lt;br /&gt;
*Pages Router : 旧来から提供されている&lt;br /&gt;
*App Router : Next.js 13から導入された新しいルーター(推奨)&lt;br /&gt;
&lt;br /&gt;
====App Router====&lt;br /&gt;
*フォルダベースのルーター&lt;br /&gt;
*ルート定義不要、フォルダ階層に準じてリクエストパスとコンポーネント(.jsファイル)との対応関係が決まる&lt;br /&gt;
*page.jsはファイル名も固定でフォルダー構造だけでリクエストパスが決定される&lt;br /&gt;
*デフォルトで作成したコンポーネントがサーバーコンポーネントになる&lt;br /&gt;
*クライアントコンポーネントにするにはuse clientを記述する必要がある&lt;br /&gt;
&lt;br /&gt;
=====アプリ共通の外枠=====&lt;br /&gt;
*layout.js&lt;br /&gt;
*&amp;amp;lt;html&amp;amp;gt;、&amp;amp;lt;body&amp;amp;gt; 要素が存在し、個々のページを埋め込むため chilrenプロパティを引用していることが条件&lt;br /&gt;
&lt;br /&gt;
===ルートパラメータ===&lt;br /&gt;
*[名前] ： 単一パラメータ&lt;br /&gt;
*[...名前] : キャッチオールセグメント&lt;br /&gt;
*&amp;lt;nowiki&amp;gt;[[...名前]]&amp;lt;/nowiki&amp;gt; : 省略可能なキャッチオールセグメント&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ App Routerのルートパラメータ&lt;br /&gt;
|-&lt;br /&gt;
! フォルダ階層 !! 対応リクエスト !! パラメータ&lt;br /&gt;
|-&lt;br /&gt;
| /app/hoge/[id]/page.js || /hoge/001 || { id : '001' }&lt;br /&gt;
|-&lt;br /&gt;
| /app/foo/[...keys]/page.js || /foo/aaa/bbb || { keys: ['aaa', 'bbb'] }&lt;br /&gt;
|-&lt;br /&gt;
| /app/bar/&amp;lt;nowiki&amp;gt;[[...keys]]&amp;lt;/nowiki&amp;gt;/page.js || /bar || {}&lt;br /&gt;
|-&lt;br /&gt;
| 〃 || /bar/aaa/bbb || { keys: ['aaa', 'bbb'] }&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Tailwind CSS==&lt;br /&gt;
*https://tailwindcss.com/&lt;br /&gt;
*ユーティリティファーストをコンセプトに開発されたCSSフレームワーク&lt;br /&gt;
*ユーティリティを組み合わせてデザインを作るので独自のスタイルを作りやすく細かな調整もしやすいメリット&lt;br /&gt;
*標準のサイズ、カラーなどは用意されている&lt;br /&gt;
&lt;br /&gt;
[https://tailwindcsscheatsheet.com/ Cheat Sheet]&lt;br /&gt;
&lt;br /&gt;
*Tailwind　CSSによるスタイルを適用&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import &amp;quot;./globals.css&amp;quot;;&lt;br /&gt;
    :&lt;br /&gt;
&lt;br /&gt;
&amp;amp;lt;ul className=&amp;quot;fle bg-blue-600 mb-4 pl-2&amp;quot;&amp;amp;gt;...&amp;amp;lt;/ul&amp;amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Prisma==&lt;br /&gt;
*JavaScriptアプリからデータベース操作を取り持つO/Rマッパー&lt;br /&gt;
===インストール===&lt;br /&gt;
*成功すると以下のファイルが生成される&lt;br /&gt;
**.env : 環境変数ファイル、gitignore に追加する&lt;br /&gt;
** prisma/schema.prisma : Prismaのスキーマファイル&lt;br /&gt;
&lt;br /&gt;
sqliteでの構成例&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ npm install prisma --save-dev&lt;br /&gt;
 $ npx prisma init --datasource-provider sqlite&lt;br /&gt;
 warn You already have a .gitignore file. Don't forget to add `.env` in it to not commit any private information.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===データモデルの定義===&lt;br /&gt;
*prisma/schema.prisma に追記&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
model　reviews {&lt;br /&gt;
  id          String @id&lt;br /&gt;
  title       String&lt;br /&gt;
  author      String&lt;br /&gt;
  price       Int&lt;br /&gt;
  publlisher  String&lt;br /&gt;
  published   String&lt;br /&gt;
  image       String&lt;br /&gt;
  read        DateTime  @default(now())&lt;br /&gt;
  memo        String&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*DBに反映&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ npx prisma db push&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Prisma Studio(Webベース管理ツール)で確認&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ npx prisma studio&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Error: @prisma/client did not initialize yet. Please run &amp;quot;prisma generate&amp;quot; and try to import it again.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ nps prisma generate&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import { PrismaClient } from &amp;quot;@prisma/client&amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Prisma Clientの利用&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import { PrismaClient } from &amp;quot;@prisma/client&amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==サーバーアクション==&lt;br /&gt;
*Next.js内蔵の仕組み&lt;br /&gt;
*ページコンポーネント、イベントハンドラー、&amp;amp;lt;form&amp;amp;lt;要素のaction属性などからサーバーコードを呼び出す仕組み&lt;br /&gt;
*サーバーとのやりとりに際し、fetchなどの非同期通信コードの不要となり、例えばコンポーネントからデータベースを操作するにも直感的なコードを記述できる&lt;br /&gt;
*現時点ではα版&lt;br /&gt;
&lt;br /&gt;
===有効化===&lt;br /&gt;
&lt;br /&gt;
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]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
const nextConfig = {&lt;br /&gt;
    experimental: {&lt;br /&gt;
        serverActions: true&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=コンポーネントの処理=&lt;br /&gt;
*[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 サーバーとクライアントの構成パターン]&lt;br /&gt;
&lt;br /&gt;
==サーバー側で実行==&lt;br /&gt;
*Next.jsの基本はサーバー側でコンポーネントを処理&lt;br /&gt;
*メリット&lt;br /&gt;
**サーバーリソースの活用&lt;br /&gt;
**ダウンロードコードサイズの最小化&lt;br /&gt;
**機密情報(サクセストークンなど)の管理&lt;br /&gt;
*クライアントに依存する操作には対応していない&lt;br /&gt;
**State関連操作(useState,useReducer,useEffectなど)&lt;br /&gt;
**イベントリスナー(onXxxxx)&lt;br /&gt;
**ブラウザAPIアクセス&lt;br /&gt;
**上記を伴うカスタムフック&lt;br /&gt;
**クラスコンポーネント利用&lt;br /&gt;
&lt;br /&gt;
==クライアント側で実行==&lt;br /&gt;
*ファイルの先頭に、'use client'ディレクティブを記述することでコンポーネントをクライアント側で実行可&lt;br /&gt;
&lt;br /&gt;
=実装=&lt;br /&gt;
&lt;br /&gt;
==ルートレイアウト==&lt;br /&gt;
===アプリ内のリンクにはLinkコンポーネントを利用===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import Link from &amp;quot;next/link&amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
規定で以下のようなコンポーネントが用意されており、アプリ内リソースを効率的に利用できる&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ コンポーネント&lt;br /&gt;
|-&lt;br /&gt;
! コンポーネント !! 概要&lt;br /&gt;
|-&lt;br /&gt;
| &amp;amp;lt;Link&amp;amp;gt; || リンクを生成&lt;br /&gt;
|-&lt;br /&gt;
| &amp;amp;lt;Script&amp;amp;gt; || スクリプトのロード&lt;br /&gt;
|-&lt;br /&gt;
| &amp;amp;lt;Image&amp;amp;gt; || 画像を表示&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===メタデータ===&lt;br /&gt;
*メタデータを定義しておくことで、個々のページに適切なヘッダーなどを埋め込める&lt;br /&gt;
*複数箇所で宣言された場合、シャローマージされる&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
export const metadata: Metadata = {&lt;br /&gt;
  title: &amp;quot;Reading Recorder&amp;quot;,&lt;br /&gt;
  description: &amp;quot;自分が読んだ書籍の記録を残す&amp;quot;,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*generateMetadata関数を利用しデータベースなどから取得した結果を元に動的に生成も可能&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
export async function generateMetadata({ params, searchParams }) {&lt;br /&gt;
    :&lt;br /&gt;
    return {&lt;br /&gt;
        title : result.title,&lt;br /&gt;
            :&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Route Segment Config===&lt;br /&gt;
*レイアウト、ページ単位の設定 &lt;br /&gt;
*あらかじめ決められた名前の変数をエクスポートしておくことで、個別の設定を施せる&lt;br /&gt;
*force-dynamic : 極力キャッシュを無効にし、ページを動的に描画しようとする&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
export const dynamic = 'force-dynamic'&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=フォント=&lt;br /&gt;
*Googleフォント(無償フォントのディレクトリサービス)を有効化&lt;br /&gt;
*具体的なフォントはGoogleフォントから自由に選択できるが一般的にはバリアブルフォント推奨(下例ではInconsolata)&lt;br /&gt;
*フォントはファイルサイズが大きいので、subsetで利用する文字のみ取り出す&lt;br /&gt;
*fnc.className でフォントを適用できる&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import { Inconsolata } from 'next/font/google';&lt;br /&gt;
const fnt = Inconsolata({ subsets: ['latin'] });&lt;br /&gt;
&lt;br /&gt;
  :&lt;br /&gt;
&amp;amp;lt;body className={`${fnt.className}` }&amp;amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=MUI=&lt;br /&gt;
[[MUI]]&lt;br /&gt;
&lt;br /&gt;
=Tips=&lt;br /&gt;
&lt;br /&gt;
==リモートホストからの画像表示を許可する==&lt;br /&gt;
*next.config.mjs&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
const nextConfig = {&lt;br /&gt;
&lt;br /&gt;
    :&lt;br /&gt;
&lt;br /&gt;
    images: {&lt;br /&gt;
        remotePatterns: [&lt;br /&gt;
            {&lt;br /&gt;
                hostname: 'books.google.com'&lt;br /&gt;
            } &lt;br /&gt;
        ] &lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Piroto</name></author>
		
	</entry>
	<entry>
		<id>https://www.typea.info/tips_/index.php?title=Next.js&amp;diff=35347</id>
		<title>Next.js</title>
		<link rel="alternate" type="text/html" href="https://www.typea.info/tips_/index.php?title=Next.js&amp;diff=35347"/>
		<updated>2024-10-05T15:48:46Z</updated>

		<summary type="html">&lt;p&gt;Piroto: /* App Router */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[React]] | [[MUI]] |&lt;br /&gt;
&lt;br /&gt;
{{amazon|4815619484}}&lt;br /&gt;
&lt;br /&gt;
=概要=&lt;br /&gt;
*[https://ja.next-community-docs.dev/docs/app-router/getting-started/ Next.js Document]&lt;br /&gt;
*Reactは、あくまでUI部分のみ&lt;br /&gt;
*本格的なアプリ開発には周辺領域を担うためのフレームワークが必要&lt;br /&gt;
*Reactベースのフレームワークとしてデファクトスタンダードと言える存在&lt;br /&gt;
*主なライブラリ&lt;br /&gt;
**ファイルシステムベースの設定レスルーター&lt;br /&gt;
**サーバーコンポーネント&lt;br /&gt;
**データ取得用fetchメソッド&lt;br /&gt;
**リソース組み込みの自動最適化&lt;br /&gt;
**CSSフレームワーク、Tailwind　CSSへの標準対応&lt;br /&gt;
&lt;br /&gt;
=導入=&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
newdelhi:Workspaces piroto$ npx create-next-app@latest&lt;br /&gt;
Need to install the following packages:&lt;br /&gt;
create-next-app@14.2.14&lt;br /&gt;
Ok to proceed? (y) y&lt;br /&gt;
&lt;br /&gt;
✔ What is your project named? … first-nextjs-app&lt;br /&gt;
✔ Would you like to use TypeScript? … No / Yes&lt;br /&gt;
✔ Would you like to use ESLint? … No / Yes&lt;br /&gt;
✔ Would you like to use Tailwind CSS? … No / Yes&lt;br /&gt;
✔ Would you like to use `src/` directory? … No / Yes&lt;br /&gt;
✔ Would you like to use App Router? (recommended) … No / Yes&lt;br /&gt;
✔ Would you like to customize the default import alias (@/*)? … No / Yes&lt;br /&gt;
Creating a new Next.js app in /Users/piroto/Workspaces/first-nextjs-app.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==実行==&lt;br /&gt;
===開発===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
npm run dev&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Start_next_js.png | 300px]]&lt;br /&gt;
&lt;br /&gt;
===本番ビルド＋実行===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
npm run build&lt;br /&gt;
npm start&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==App Router==&lt;br /&gt;
*React Routerとは異なる独自のルーターを標準で提供&lt;br /&gt;
*コンポーネントそのものはReactと変わらない&lt;br /&gt;
&lt;br /&gt;
===2種類のルーター===&lt;br /&gt;
&lt;br /&gt;
*Pages Router : 旧来から提供されている&lt;br /&gt;
*App Router : Next.js 13から導入された新しいルーター(推奨)&lt;br /&gt;
&lt;br /&gt;
====App Router====&lt;br /&gt;
*フォルダベースのルーター&lt;br /&gt;
*ルート定義不要、フォルダ階層に準じてリクエストパスとコンポーネント(.jsファイル)との対応関係が決まる&lt;br /&gt;
*page.jsはファイル名も固定でフォルダー構造だけでリクエストパスが決定される&lt;br /&gt;
*デフォルトで作成したコンポーネントがサーバーコンポーネントになる&lt;br /&gt;
*クライアントコンポーネントにするにはuse clientを記述する必要がある&lt;br /&gt;
&lt;br /&gt;
=====アプリ共通の外枠=====&lt;br /&gt;
*layout.js&lt;br /&gt;
*&amp;amp;lt;html&amp;amp;gt;、&amp;amp;lt;body&amp;amp;gt; 要素が存在し、個々のページを埋め込むため chilrenプロパティを引用していることが条件&lt;br /&gt;
&lt;br /&gt;
===ルートパラメータ===&lt;br /&gt;
*[名前] ： 単一パラメータ&lt;br /&gt;
*[...名前] : キャッチオールセグメント&lt;br /&gt;
*&amp;lt;nowiki&amp;gt;[[...名前]]&amp;lt;/nowiki&amp;gt; : 省略可能なキャッチオールセグメント&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ App Routerのルートパラメータ&lt;br /&gt;
|-&lt;br /&gt;
! フォルダ階層 !! 対応リクエスト !! パラメータ&lt;br /&gt;
|-&lt;br /&gt;
| /app/hoge/[id]/page.js || /hoge/001 || { id : '001' }&lt;br /&gt;
|-&lt;br /&gt;
| /app/foo/[...keys]/page.js || /foo/aaa/bbb || { keys: ['aaa', 'bbb'] }&lt;br /&gt;
|-&lt;br /&gt;
| /app/bar/&amp;lt;nowiki&amp;gt;[[...keys]]&amp;lt;/nowiki&amp;gt;/page.js || /bar || {}&lt;br /&gt;
|-&lt;br /&gt;
| 〃 || /bar/aaa/bbb || { keys: ['aaa', 'bbb'] }&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Tailwind CSS==&lt;br /&gt;
*https://tailwindcss.com/&lt;br /&gt;
*ユーティリティファーストをコンセプトに開発されたCSSフレームワーク&lt;br /&gt;
*ユーティリティを組み合わせてデザインを作るので独自のスタイルを作りやすく細かな調整もしやすいメリット&lt;br /&gt;
*標準のサイズ、カラーなどは用意されている&lt;br /&gt;
&lt;br /&gt;
[https://tailwindcsscheatsheet.com/ Cheat Sheet]&lt;br /&gt;
&lt;br /&gt;
*Tailwind　CSSによるスタイルを適用&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import &amp;quot;./globals.css&amp;quot;;&lt;br /&gt;
    :&lt;br /&gt;
&lt;br /&gt;
&amp;amp;lt;ul className=&amp;quot;fle bg-blue-600 mb-4 pl-2&amp;quot;&amp;amp;gt;...&amp;amp;lt;/ul&amp;amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Prisma==&lt;br /&gt;
*JavaScriptアプリからデータベース操作を取り持つO/Rマッパー&lt;br /&gt;
===インストール===&lt;br /&gt;
*成功すると以下のファイルが生成される&lt;br /&gt;
**.env : 環境変数ファイル、gitignore に追加する&lt;br /&gt;
** prisma/schema.prisma : Prismaのスキーマファイル&lt;br /&gt;
&lt;br /&gt;
sqliteでの構成例&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ npm install prisma --save-dev&lt;br /&gt;
 $ npx prisma init --datasource-provider sqlite&lt;br /&gt;
 warn You already have a .gitignore file. Don't forget to add `.env` in it to not commit any private information.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===データモデルの定義===&lt;br /&gt;
*prisma/schema.prisma に追記&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
model　reviews {&lt;br /&gt;
  id          String @id&lt;br /&gt;
  title       String&lt;br /&gt;
  author      String&lt;br /&gt;
  price       Int&lt;br /&gt;
  publlisher  String&lt;br /&gt;
  published   String&lt;br /&gt;
  image       String&lt;br /&gt;
  read        DateTime  @default(now())&lt;br /&gt;
  memo        String&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*DBに反映&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ npx prisma db push&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Prisma Studio(Webベース管理ツール)で確認&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ npx prisma studio&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Error: @prisma/client did not initialize yet. Please run &amp;quot;prisma generate&amp;quot; and try to import it again.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ nps prisma generate&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import { PrismaClient } from &amp;quot;@prisma/client&amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Prisma Clientの利用&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import { PrismaClient } from &amp;quot;@prisma/client&amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==サーバーアクション==&lt;br /&gt;
*Next.js内蔵の仕組み&lt;br /&gt;
*ページコンポーネント、イベントハンドラー、&amp;amp;lt;form&amp;amp;lt;要素のaction属性などからサーバーコードを呼び出す仕組み&lt;br /&gt;
*サーバーとのやりとりに際し、fetchなどの非同期通信コードの不要となり、例えばコンポーネントからデータベースを操作するにも直感的なコードを記述できる&lt;br /&gt;
*現時点ではα版&lt;br /&gt;
&lt;br /&gt;
===有効化===&lt;br /&gt;
&lt;br /&gt;
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]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
const nextConfig = {&lt;br /&gt;
    experimental: {&lt;br /&gt;
        serverActions: true&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=コンポーネントの処理=&lt;br /&gt;
*[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 サーバーとクライアントの構成パターン]&lt;br /&gt;
&lt;br /&gt;
==サーバー側で実行==&lt;br /&gt;
*Next.jsの基本はサーバー側でコンポーネントを処理&lt;br /&gt;
*メリット&lt;br /&gt;
**サーバーリソースの活用&lt;br /&gt;
**ダウンロードコードサイズの最小化&lt;br /&gt;
**機密情報(サクセストークンなど)の管理&lt;br /&gt;
*クライアントに依存する操作には対応していない&lt;br /&gt;
**State関連操作(useState,useReducer,useEffectなど)&lt;br /&gt;
**イベントリスナー(onXxxxx)&lt;br /&gt;
**ブラウザAPIアクセス&lt;br /&gt;
**上記を伴うカスタムフック&lt;br /&gt;
**クラスコンポーネント利用&lt;br /&gt;
&lt;br /&gt;
==クライアント側で実行==&lt;br /&gt;
*ファイルの先頭に、'use client'ディレクティブを記述することでコンポーネントをクライアント側で実行可&lt;br /&gt;
&lt;br /&gt;
=実装=&lt;br /&gt;
&lt;br /&gt;
==ルートレイアウト==&lt;br /&gt;
===アプリ内のリンクにはLinkコンポーネントを利用===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import Link from &amp;quot;next/link&amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
規定で以下のようなコンポーネントが用意されており、アプリ内リソースを効率的に利用できる&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ コンポーネント&lt;br /&gt;
|-&lt;br /&gt;
! コンポーネント !! 概要&lt;br /&gt;
|-&lt;br /&gt;
| &amp;amp;lt;Link&amp;amp;gt; || リンクを生成&lt;br /&gt;
|-&lt;br /&gt;
| &amp;amp;lt;Script&amp;amp;gt; || スクリプトのロード&lt;br /&gt;
|-&lt;br /&gt;
| &amp;amp;lt;Image&amp;amp;gt; || 画像を表示&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===メタデータ===&lt;br /&gt;
*メタデータを定義しておくことで、個々のページに適切なヘッダーなどを埋め込める&lt;br /&gt;
*複数箇所で宣言された場合、シャローマージされる&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
export const metadata: Metadata = {&lt;br /&gt;
  title: &amp;quot;Reading Recorder&amp;quot;,&lt;br /&gt;
  description: &amp;quot;自分が読んだ書籍の記録を残す&amp;quot;,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*generateMetadata関数を利用しデータベースなどから取得した結果を元に動的に生成も可能&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
export async function generateMetadata({ params, searchParams }) {&lt;br /&gt;
    :&lt;br /&gt;
    return {&lt;br /&gt;
        title : result.title,&lt;br /&gt;
            :&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Route Segment Config===&lt;br /&gt;
*レイアウト、ページ単位の設定 &lt;br /&gt;
*あらかじめ決められた名前の変数をエクスポートしておくことで、個別の設定を施せる&lt;br /&gt;
*force-dynamic : 極力キャッシュを無効にし、ページを動的に描画しようとする&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
export const dynamic = 'force-dynamic'&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=フォント=&lt;br /&gt;
*Googleフォント(無償フォントのディレクトリサービス)を有効化&lt;br /&gt;
*具体的なフォントはGoogleフォントから自由に選択できるが一般的にはバリアブルフォント推奨(下例ではInconsolata)&lt;br /&gt;
*フォントはファイルサイズが大きいので、subsetで利用する文字のみ取り出す&lt;br /&gt;
*fnc.className でフォントを適用できる&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import { Inconsolata } from 'next/font/google';&lt;br /&gt;
const fnt = Inconsolata({ subsets: ['latin'] });&lt;br /&gt;
&lt;br /&gt;
  :&lt;br /&gt;
&amp;amp;lt;body className={`${fnt.className}` }&amp;amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=MUI=&lt;br /&gt;
[[MUI]]&lt;br /&gt;
&lt;br /&gt;
=Tips=&lt;br /&gt;
&lt;br /&gt;
==リモートホストからの画像表示を許可する==&lt;br /&gt;
*next.config.mjs&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
const nextConfig = {&lt;br /&gt;
&lt;br /&gt;
    :&lt;br /&gt;
&lt;br /&gt;
    images: {&lt;br /&gt;
        remotePatterns: [&lt;br /&gt;
            {&lt;br /&gt;
                hostname: 'books.google.com'&lt;br /&gt;
            } &lt;br /&gt;
        ] &lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Piroto</name></author>
		
	</entry>
	<entry>
		<id>https://www.typea.info/tips_/index.php?title=Next.js&amp;diff=35346</id>
		<title>Next.js</title>
		<link rel="alternate" type="text/html" href="https://www.typea.info/tips_/index.php?title=Next.js&amp;diff=35346"/>
		<updated>2024-10-05T15:43:33Z</updated>

		<summary type="html">&lt;p&gt;Piroto: /* 概要 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[React]] | [[MUI]] |&lt;br /&gt;
&lt;br /&gt;
{{amazon|4815619484}}&lt;br /&gt;
&lt;br /&gt;
=概要=&lt;br /&gt;
*[https://ja.next-community-docs.dev/docs/app-router/getting-started/ Next.js Document]&lt;br /&gt;
*Reactは、あくまでUI部分のみ&lt;br /&gt;
*本格的なアプリ開発には周辺領域を担うためのフレームワークが必要&lt;br /&gt;
*Reactベースのフレームワークとしてデファクトスタンダードと言える存在&lt;br /&gt;
*主なライブラリ&lt;br /&gt;
**ファイルシステムベースの設定レスルーター&lt;br /&gt;
**サーバーコンポーネント&lt;br /&gt;
**データ取得用fetchメソッド&lt;br /&gt;
**リソース組み込みの自動最適化&lt;br /&gt;
**CSSフレームワーク、Tailwind　CSSへの標準対応&lt;br /&gt;
&lt;br /&gt;
=導入=&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
newdelhi:Workspaces piroto$ npx create-next-app@latest&lt;br /&gt;
Need to install the following packages:&lt;br /&gt;
create-next-app@14.2.14&lt;br /&gt;
Ok to proceed? (y) y&lt;br /&gt;
&lt;br /&gt;
✔ What is your project named? … first-nextjs-app&lt;br /&gt;
✔ Would you like to use TypeScript? … No / Yes&lt;br /&gt;
✔ Would you like to use ESLint? … No / Yes&lt;br /&gt;
✔ Would you like to use Tailwind CSS? … No / Yes&lt;br /&gt;
✔ Would you like to use `src/` directory? … No / Yes&lt;br /&gt;
✔ Would you like to use App Router? (recommended) … No / Yes&lt;br /&gt;
✔ Would you like to customize the default import alias (@/*)? … No / Yes&lt;br /&gt;
Creating a new Next.js app in /Users/piroto/Workspaces/first-nextjs-app.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==実行==&lt;br /&gt;
===開発===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
npm run dev&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Start_next_js.png | 300px]]&lt;br /&gt;
&lt;br /&gt;
===本番ビルド＋実行===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
npm run build&lt;br /&gt;
npm start&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==App Router==&lt;br /&gt;
*React Routerとは異なる独自のルーターを標準で提供&lt;br /&gt;
*コンポーネントそのものはReactと変わらない&lt;br /&gt;
&lt;br /&gt;
===2種類のルーター===&lt;br /&gt;
&lt;br /&gt;
*Pages Router : 旧来から提供されている&lt;br /&gt;
*App Router : Next.js 13から導入された新しいルーター(推奨)&lt;br /&gt;
&lt;br /&gt;
====App Router====&lt;br /&gt;
*フォルダベースのルーター&lt;br /&gt;
*ルート定義不要、フォルダ階層に準じてリクエストパスとコンポーネント(.jsファイル)との対応関係が決まる&lt;br /&gt;
*page.jsはファイル名も固定でフォルダー構造だけでリクエストパスが決定される&lt;br /&gt;
&lt;br /&gt;
=====アプリ共通の外枠=====&lt;br /&gt;
*layout.js&lt;br /&gt;
*&amp;amp;lt;html&amp;amp;gt;、&amp;amp;lt;body&amp;amp;gt; 要素が存在し、個々のページを埋め込むため chilrenプロパティを引用していることが条件&lt;br /&gt;
&lt;br /&gt;
===ルートパラメータ===&lt;br /&gt;
*[名前] ： 単一パラメータ&lt;br /&gt;
*[...名前] : キャッチオールセグメント&lt;br /&gt;
*&amp;lt;nowiki&amp;gt;[[...名前]]&amp;lt;/nowiki&amp;gt; : 省略可能なキャッチオールセグメント&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ App Routerのルートパラメータ&lt;br /&gt;
|-&lt;br /&gt;
! フォルダ階層 !! 対応リクエスト !! パラメータ&lt;br /&gt;
|-&lt;br /&gt;
| /app/hoge/[id]/page.js || /hoge/001 || { id : '001' }&lt;br /&gt;
|-&lt;br /&gt;
| /app/foo/[...keys]/page.js || /foo/aaa/bbb || { keys: ['aaa', 'bbb'] }&lt;br /&gt;
|-&lt;br /&gt;
| /app/bar/&amp;lt;nowiki&amp;gt;[[...keys]]&amp;lt;/nowiki&amp;gt;/page.js || /bar || {}&lt;br /&gt;
|-&lt;br /&gt;
| 〃 || /bar/aaa/bbb || { keys: ['aaa', 'bbb'] }&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Tailwind CSS==&lt;br /&gt;
*https://tailwindcss.com/&lt;br /&gt;
*ユーティリティファーストをコンセプトに開発されたCSSフレームワーク&lt;br /&gt;
*ユーティリティを組み合わせてデザインを作るので独自のスタイルを作りやすく細かな調整もしやすいメリット&lt;br /&gt;
*標準のサイズ、カラーなどは用意されている&lt;br /&gt;
&lt;br /&gt;
[https://tailwindcsscheatsheet.com/ Cheat Sheet]&lt;br /&gt;
&lt;br /&gt;
*Tailwind　CSSによるスタイルを適用&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import &amp;quot;./globals.css&amp;quot;;&lt;br /&gt;
    :&lt;br /&gt;
&lt;br /&gt;
&amp;amp;lt;ul className=&amp;quot;fle bg-blue-600 mb-4 pl-2&amp;quot;&amp;amp;gt;...&amp;amp;lt;/ul&amp;amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Prisma==&lt;br /&gt;
*JavaScriptアプリからデータベース操作を取り持つO/Rマッパー&lt;br /&gt;
===インストール===&lt;br /&gt;
*成功すると以下のファイルが生成される&lt;br /&gt;
**.env : 環境変数ファイル、gitignore に追加する&lt;br /&gt;
** prisma/schema.prisma : Prismaのスキーマファイル&lt;br /&gt;
&lt;br /&gt;
sqliteでの構成例&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ npm install prisma --save-dev&lt;br /&gt;
 $ npx prisma init --datasource-provider sqlite&lt;br /&gt;
 warn You already have a .gitignore file. Don't forget to add `.env` in it to not commit any private information.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===データモデルの定義===&lt;br /&gt;
*prisma/schema.prisma に追記&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
model　reviews {&lt;br /&gt;
  id          String @id&lt;br /&gt;
  title       String&lt;br /&gt;
  author      String&lt;br /&gt;
  price       Int&lt;br /&gt;
  publlisher  String&lt;br /&gt;
  published   String&lt;br /&gt;
  image       String&lt;br /&gt;
  read        DateTime  @default(now())&lt;br /&gt;
  memo        String&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*DBに反映&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ npx prisma db push&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Prisma Studio(Webベース管理ツール)で確認&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ npx prisma studio&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Error: @prisma/client did not initialize yet. Please run &amp;quot;prisma generate&amp;quot; and try to import it again.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ nps prisma generate&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import { PrismaClient } from &amp;quot;@prisma/client&amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Prisma Clientの利用&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import { PrismaClient } from &amp;quot;@prisma/client&amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==サーバーアクション==&lt;br /&gt;
*Next.js内蔵の仕組み&lt;br /&gt;
*ページコンポーネント、イベントハンドラー、&amp;amp;lt;form&amp;amp;lt;要素のaction属性などからサーバーコードを呼び出す仕組み&lt;br /&gt;
*サーバーとのやりとりに際し、fetchなどの非同期通信コードの不要となり、例えばコンポーネントからデータベースを操作するにも直感的なコードを記述できる&lt;br /&gt;
*現時点ではα版&lt;br /&gt;
&lt;br /&gt;
===有効化===&lt;br /&gt;
&lt;br /&gt;
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]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
const nextConfig = {&lt;br /&gt;
    experimental: {&lt;br /&gt;
        serverActions: true&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=コンポーネントの処理=&lt;br /&gt;
*[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 サーバーとクライアントの構成パターン]&lt;br /&gt;
&lt;br /&gt;
==サーバー側で実行==&lt;br /&gt;
*Next.jsの基本はサーバー側でコンポーネントを処理&lt;br /&gt;
*メリット&lt;br /&gt;
**サーバーリソースの活用&lt;br /&gt;
**ダウンロードコードサイズの最小化&lt;br /&gt;
**機密情報(サクセストークンなど)の管理&lt;br /&gt;
*クライアントに依存する操作には対応していない&lt;br /&gt;
**State関連操作(useState,useReducer,useEffectなど)&lt;br /&gt;
**イベントリスナー(onXxxxx)&lt;br /&gt;
**ブラウザAPIアクセス&lt;br /&gt;
**上記を伴うカスタムフック&lt;br /&gt;
**クラスコンポーネント利用&lt;br /&gt;
&lt;br /&gt;
==クライアント側で実行==&lt;br /&gt;
*ファイルの先頭に、'use client'ディレクティブを記述することでコンポーネントをクライアント側で実行可&lt;br /&gt;
&lt;br /&gt;
=実装=&lt;br /&gt;
&lt;br /&gt;
==ルートレイアウト==&lt;br /&gt;
===アプリ内のリンクにはLinkコンポーネントを利用===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import Link from &amp;quot;next/link&amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
規定で以下のようなコンポーネントが用意されており、アプリ内リソースを効率的に利用できる&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ コンポーネント&lt;br /&gt;
|-&lt;br /&gt;
! コンポーネント !! 概要&lt;br /&gt;
|-&lt;br /&gt;
| &amp;amp;lt;Link&amp;amp;gt; || リンクを生成&lt;br /&gt;
|-&lt;br /&gt;
| &amp;amp;lt;Script&amp;amp;gt; || スクリプトのロード&lt;br /&gt;
|-&lt;br /&gt;
| &amp;amp;lt;Image&amp;amp;gt; || 画像を表示&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===メタデータ===&lt;br /&gt;
*メタデータを定義しておくことで、個々のページに適切なヘッダーなどを埋め込める&lt;br /&gt;
*複数箇所で宣言された場合、シャローマージされる&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
export const metadata: Metadata = {&lt;br /&gt;
  title: &amp;quot;Reading Recorder&amp;quot;,&lt;br /&gt;
  description: &amp;quot;自分が読んだ書籍の記録を残す&amp;quot;,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*generateMetadata関数を利用しデータベースなどから取得した結果を元に動的に生成も可能&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
export async function generateMetadata({ params, searchParams }) {&lt;br /&gt;
    :&lt;br /&gt;
    return {&lt;br /&gt;
        title : result.title,&lt;br /&gt;
            :&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Route Segment Config===&lt;br /&gt;
*レイアウト、ページ単位の設定 &lt;br /&gt;
*あらかじめ決められた名前の変数をエクスポートしておくことで、個別の設定を施せる&lt;br /&gt;
*force-dynamic : 極力キャッシュを無効にし、ページを動的に描画しようとする&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
export const dynamic = 'force-dynamic'&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=フォント=&lt;br /&gt;
*Googleフォント(無償フォントのディレクトリサービス)を有効化&lt;br /&gt;
*具体的なフォントはGoogleフォントから自由に選択できるが一般的にはバリアブルフォント推奨(下例ではInconsolata)&lt;br /&gt;
*フォントはファイルサイズが大きいので、subsetで利用する文字のみ取り出す&lt;br /&gt;
*fnc.className でフォントを適用できる&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import { Inconsolata } from 'next/font/google';&lt;br /&gt;
const fnt = Inconsolata({ subsets: ['latin'] });&lt;br /&gt;
&lt;br /&gt;
  :&lt;br /&gt;
&amp;amp;lt;body className={`${fnt.className}` }&amp;amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=MUI=&lt;br /&gt;
[[MUI]]&lt;br /&gt;
&lt;br /&gt;
=Tips=&lt;br /&gt;
&lt;br /&gt;
==リモートホストからの画像表示を許可する==&lt;br /&gt;
*next.config.mjs&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
const nextConfig = {&lt;br /&gt;
&lt;br /&gt;
    :&lt;br /&gt;
&lt;br /&gt;
    images: {&lt;br /&gt;
        remotePatterns: [&lt;br /&gt;
            {&lt;br /&gt;
                hostname: 'books.google.com'&lt;br /&gt;
            } &lt;br /&gt;
        ] &lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Piroto</name></author>
		
	</entry>
	<entry>
		<id>https://www.typea.info/tips_/index.php?title=Next.js&amp;diff=35345</id>
		<title>Next.js</title>
		<link rel="alternate" type="text/html" href="https://www.typea.info/tips_/index.php?title=Next.js&amp;diff=35345"/>
		<updated>2024-10-05T15:41:24Z</updated>

		<summary type="html">&lt;p&gt;Piroto: /* コンポーネントの処理 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[React]] | [[MUI]] |&lt;br /&gt;
&lt;br /&gt;
{{amazon|4815619484}}&lt;br /&gt;
&lt;br /&gt;
=概要=&lt;br /&gt;
*Reactは、あくまでUI部分のみ&lt;br /&gt;
*本格的なアプリ開発には周辺領域を担うためのフレームワークが必要&lt;br /&gt;
*Reactベースのフレームワークとしてデファクトスタンダードと言える存在&lt;br /&gt;
*主なライブラリ&lt;br /&gt;
**ファイルシステムベースの設定レスルーター&lt;br /&gt;
**サーバーコンポーネント&lt;br /&gt;
**データ取得用fetchメソッド&lt;br /&gt;
**リソース組み込みの自動最適化&lt;br /&gt;
**CSSフレームワーク、Tailwind　CSSへの標準対応&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=導入=&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
newdelhi:Workspaces piroto$ npx create-next-app@latest&lt;br /&gt;
Need to install the following packages:&lt;br /&gt;
create-next-app@14.2.14&lt;br /&gt;
Ok to proceed? (y) y&lt;br /&gt;
&lt;br /&gt;
✔ What is your project named? … first-nextjs-app&lt;br /&gt;
✔ Would you like to use TypeScript? … No / Yes&lt;br /&gt;
✔ Would you like to use ESLint? … No / Yes&lt;br /&gt;
✔ Would you like to use Tailwind CSS? … No / Yes&lt;br /&gt;
✔ Would you like to use `src/` directory? … No / Yes&lt;br /&gt;
✔ Would you like to use App Router? (recommended) … No / Yes&lt;br /&gt;
✔ Would you like to customize the default import alias (@/*)? … No / Yes&lt;br /&gt;
Creating a new Next.js app in /Users/piroto/Workspaces/first-nextjs-app.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==実行==&lt;br /&gt;
===開発===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
npm run dev&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Start_next_js.png | 300px]]&lt;br /&gt;
&lt;br /&gt;
===本番ビルド＋実行===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
npm run build&lt;br /&gt;
npm start&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==App Router==&lt;br /&gt;
*React Routerとは異なる独自のルーターを標準で提供&lt;br /&gt;
*コンポーネントそのものはReactと変わらない&lt;br /&gt;
&lt;br /&gt;
===2種類のルーター===&lt;br /&gt;
&lt;br /&gt;
*Pages Router : 旧来から提供されている&lt;br /&gt;
*App Router : Next.js 13から導入された新しいルーター(推奨)&lt;br /&gt;
&lt;br /&gt;
====App Router====&lt;br /&gt;
*フォルダベースのルーター&lt;br /&gt;
*ルート定義不要、フォルダ階層に準じてリクエストパスとコンポーネント(.jsファイル)との対応関係が決まる&lt;br /&gt;
*page.jsはファイル名も固定でフォルダー構造だけでリクエストパスが決定される&lt;br /&gt;
&lt;br /&gt;
=====アプリ共通の外枠=====&lt;br /&gt;
*layout.js&lt;br /&gt;
*&amp;amp;lt;html&amp;amp;gt;、&amp;amp;lt;body&amp;amp;gt; 要素が存在し、個々のページを埋め込むため chilrenプロパティを引用していることが条件&lt;br /&gt;
&lt;br /&gt;
===ルートパラメータ===&lt;br /&gt;
*[名前] ： 単一パラメータ&lt;br /&gt;
*[...名前] : キャッチオールセグメント&lt;br /&gt;
*&amp;lt;nowiki&amp;gt;[[...名前]]&amp;lt;/nowiki&amp;gt; : 省略可能なキャッチオールセグメント&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ App Routerのルートパラメータ&lt;br /&gt;
|-&lt;br /&gt;
! フォルダ階層 !! 対応リクエスト !! パラメータ&lt;br /&gt;
|-&lt;br /&gt;
| /app/hoge/[id]/page.js || /hoge/001 || { id : '001' }&lt;br /&gt;
|-&lt;br /&gt;
| /app/foo/[...keys]/page.js || /foo/aaa/bbb || { keys: ['aaa', 'bbb'] }&lt;br /&gt;
|-&lt;br /&gt;
| /app/bar/&amp;lt;nowiki&amp;gt;[[...keys]]&amp;lt;/nowiki&amp;gt;/page.js || /bar || {}&lt;br /&gt;
|-&lt;br /&gt;
| 〃 || /bar/aaa/bbb || { keys: ['aaa', 'bbb'] }&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Tailwind CSS==&lt;br /&gt;
*https://tailwindcss.com/&lt;br /&gt;
*ユーティリティファーストをコンセプトに開発されたCSSフレームワーク&lt;br /&gt;
*ユーティリティを組み合わせてデザインを作るので独自のスタイルを作りやすく細かな調整もしやすいメリット&lt;br /&gt;
*標準のサイズ、カラーなどは用意されている&lt;br /&gt;
&lt;br /&gt;
[https://tailwindcsscheatsheet.com/ Cheat Sheet]&lt;br /&gt;
&lt;br /&gt;
*Tailwind　CSSによるスタイルを適用&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import &amp;quot;./globals.css&amp;quot;;&lt;br /&gt;
    :&lt;br /&gt;
&lt;br /&gt;
&amp;amp;lt;ul className=&amp;quot;fle bg-blue-600 mb-4 pl-2&amp;quot;&amp;amp;gt;...&amp;amp;lt;/ul&amp;amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Prisma==&lt;br /&gt;
*JavaScriptアプリからデータベース操作を取り持つO/Rマッパー&lt;br /&gt;
===インストール===&lt;br /&gt;
*成功すると以下のファイルが生成される&lt;br /&gt;
**.env : 環境変数ファイル、gitignore に追加する&lt;br /&gt;
** prisma/schema.prisma : Prismaのスキーマファイル&lt;br /&gt;
&lt;br /&gt;
sqliteでの構成例&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ npm install prisma --save-dev&lt;br /&gt;
 $ npx prisma init --datasource-provider sqlite&lt;br /&gt;
 warn You already have a .gitignore file. Don't forget to add `.env` in it to not commit any private information.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===データモデルの定義===&lt;br /&gt;
*prisma/schema.prisma に追記&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
model　reviews {&lt;br /&gt;
  id          String @id&lt;br /&gt;
  title       String&lt;br /&gt;
  author      String&lt;br /&gt;
  price       Int&lt;br /&gt;
  publlisher  String&lt;br /&gt;
  published   String&lt;br /&gt;
  image       String&lt;br /&gt;
  read        DateTime  @default(now())&lt;br /&gt;
  memo        String&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*DBに反映&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ npx prisma db push&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Prisma Studio(Webベース管理ツール)で確認&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ npx prisma studio&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Error: @prisma/client did not initialize yet. Please run &amp;quot;prisma generate&amp;quot; and try to import it again.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ nps prisma generate&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import { PrismaClient } from &amp;quot;@prisma/client&amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Prisma Clientの利用&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import { PrismaClient } from &amp;quot;@prisma/client&amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==サーバーアクション==&lt;br /&gt;
*Next.js内蔵の仕組み&lt;br /&gt;
*ページコンポーネント、イベントハンドラー、&amp;amp;lt;form&amp;amp;lt;要素のaction属性などからサーバーコードを呼び出す仕組み&lt;br /&gt;
*サーバーとのやりとりに際し、fetchなどの非同期通信コードの不要となり、例えばコンポーネントからデータベースを操作するにも直感的なコードを記述できる&lt;br /&gt;
*現時点ではα版&lt;br /&gt;
&lt;br /&gt;
===有効化===&lt;br /&gt;
&lt;br /&gt;
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]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
const nextConfig = {&lt;br /&gt;
    experimental: {&lt;br /&gt;
        serverActions: true&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=コンポーネントの処理=&lt;br /&gt;
*[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 サーバーとクライアントの構成パターン]&lt;br /&gt;
&lt;br /&gt;
==サーバー側で実行==&lt;br /&gt;
*Next.jsの基本はサーバー側でコンポーネントを処理&lt;br /&gt;
*メリット&lt;br /&gt;
**サーバーリソースの活用&lt;br /&gt;
**ダウンロードコードサイズの最小化&lt;br /&gt;
**機密情報(サクセストークンなど)の管理&lt;br /&gt;
*クライアントに依存する操作には対応していない&lt;br /&gt;
**State関連操作(useState,useReducer,useEffectなど)&lt;br /&gt;
**イベントリスナー(onXxxxx)&lt;br /&gt;
**ブラウザAPIアクセス&lt;br /&gt;
**上記を伴うカスタムフック&lt;br /&gt;
**クラスコンポーネント利用&lt;br /&gt;
&lt;br /&gt;
==クライアント側で実行==&lt;br /&gt;
*ファイルの先頭に、'use client'ディレクティブを記述することでコンポーネントをクライアント側で実行可&lt;br /&gt;
&lt;br /&gt;
=実装=&lt;br /&gt;
&lt;br /&gt;
==ルートレイアウト==&lt;br /&gt;
===アプリ内のリンクにはLinkコンポーネントを利用===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import Link from &amp;quot;next/link&amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
規定で以下のようなコンポーネントが用意されており、アプリ内リソースを効率的に利用できる&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ コンポーネント&lt;br /&gt;
|-&lt;br /&gt;
! コンポーネント !! 概要&lt;br /&gt;
|-&lt;br /&gt;
| &amp;amp;lt;Link&amp;amp;gt; || リンクを生成&lt;br /&gt;
|-&lt;br /&gt;
| &amp;amp;lt;Script&amp;amp;gt; || スクリプトのロード&lt;br /&gt;
|-&lt;br /&gt;
| &amp;amp;lt;Image&amp;amp;gt; || 画像を表示&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===メタデータ===&lt;br /&gt;
*メタデータを定義しておくことで、個々のページに適切なヘッダーなどを埋め込める&lt;br /&gt;
*複数箇所で宣言された場合、シャローマージされる&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
export const metadata: Metadata = {&lt;br /&gt;
  title: &amp;quot;Reading Recorder&amp;quot;,&lt;br /&gt;
  description: &amp;quot;自分が読んだ書籍の記録を残す&amp;quot;,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*generateMetadata関数を利用しデータベースなどから取得した結果を元に動的に生成も可能&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
export async function generateMetadata({ params, searchParams }) {&lt;br /&gt;
    :&lt;br /&gt;
    return {&lt;br /&gt;
        title : result.title,&lt;br /&gt;
            :&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Route Segment Config===&lt;br /&gt;
*レイアウト、ページ単位の設定 &lt;br /&gt;
*あらかじめ決められた名前の変数をエクスポートしておくことで、個別の設定を施せる&lt;br /&gt;
*force-dynamic : 極力キャッシュを無効にし、ページを動的に描画しようとする&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
export const dynamic = 'force-dynamic'&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=フォント=&lt;br /&gt;
*Googleフォント(無償フォントのディレクトリサービス)を有効化&lt;br /&gt;
*具体的なフォントはGoogleフォントから自由に選択できるが一般的にはバリアブルフォント推奨(下例ではInconsolata)&lt;br /&gt;
*フォントはファイルサイズが大きいので、subsetで利用する文字のみ取り出す&lt;br /&gt;
*fnc.className でフォントを適用できる&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import { Inconsolata } from 'next/font/google';&lt;br /&gt;
const fnt = Inconsolata({ subsets: ['latin'] });&lt;br /&gt;
&lt;br /&gt;
  :&lt;br /&gt;
&amp;amp;lt;body className={`${fnt.className}` }&amp;amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=MUI=&lt;br /&gt;
[[MUI]]&lt;br /&gt;
&lt;br /&gt;
=Tips=&lt;br /&gt;
&lt;br /&gt;
==リモートホストからの画像表示を許可する==&lt;br /&gt;
*next.config.mjs&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
const nextConfig = {&lt;br /&gt;
&lt;br /&gt;
    :&lt;br /&gt;
&lt;br /&gt;
    images: {&lt;br /&gt;
        remotePatterns: [&lt;br /&gt;
            {&lt;br /&gt;
                hostname: 'books.google.com'&lt;br /&gt;
            } &lt;br /&gt;
        ] &lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Piroto</name></author>
		
	</entry>
	<entry>
		<id>https://www.typea.info/tips_/index.php?title=Next.js&amp;diff=35344</id>
		<title>Next.js</title>
		<link rel="alternate" type="text/html" href="https://www.typea.info/tips_/index.php?title=Next.js&amp;diff=35344"/>
		<updated>2024-10-05T15:40:05Z</updated>

		<summary type="html">&lt;p&gt;Piroto: /* サーバーコンポーネント */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[React]] | [[MUI]] |&lt;br /&gt;
&lt;br /&gt;
{{amazon|4815619484}}&lt;br /&gt;
&lt;br /&gt;
=概要=&lt;br /&gt;
*Reactは、あくまでUI部分のみ&lt;br /&gt;
*本格的なアプリ開発には周辺領域を担うためのフレームワークが必要&lt;br /&gt;
*Reactベースのフレームワークとしてデファクトスタンダードと言える存在&lt;br /&gt;
*主なライブラリ&lt;br /&gt;
**ファイルシステムベースの設定レスルーター&lt;br /&gt;
**サーバーコンポーネント&lt;br /&gt;
**データ取得用fetchメソッド&lt;br /&gt;
**リソース組み込みの自動最適化&lt;br /&gt;
**CSSフレームワーク、Tailwind　CSSへの標準対応&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=導入=&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
newdelhi:Workspaces piroto$ npx create-next-app@latest&lt;br /&gt;
Need to install the following packages:&lt;br /&gt;
create-next-app@14.2.14&lt;br /&gt;
Ok to proceed? (y) y&lt;br /&gt;
&lt;br /&gt;
✔ What is your project named? … first-nextjs-app&lt;br /&gt;
✔ Would you like to use TypeScript? … No / Yes&lt;br /&gt;
✔ Would you like to use ESLint? … No / Yes&lt;br /&gt;
✔ Would you like to use Tailwind CSS? … No / Yes&lt;br /&gt;
✔ Would you like to use `src/` directory? … No / Yes&lt;br /&gt;
✔ Would you like to use App Router? (recommended) … No / Yes&lt;br /&gt;
✔ Would you like to customize the default import alias (@/*)? … No / Yes&lt;br /&gt;
Creating a new Next.js app in /Users/piroto/Workspaces/first-nextjs-app.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==実行==&lt;br /&gt;
===開発===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
npm run dev&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Start_next_js.png | 300px]]&lt;br /&gt;
&lt;br /&gt;
===本番ビルド＋実行===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
npm run build&lt;br /&gt;
npm start&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==App Router==&lt;br /&gt;
*React Routerとは異なる独自のルーターを標準で提供&lt;br /&gt;
*コンポーネントそのものはReactと変わらない&lt;br /&gt;
&lt;br /&gt;
===2種類のルーター===&lt;br /&gt;
&lt;br /&gt;
*Pages Router : 旧来から提供されている&lt;br /&gt;
*App Router : Next.js 13から導入された新しいルーター(推奨)&lt;br /&gt;
&lt;br /&gt;
====App Router====&lt;br /&gt;
*フォルダベースのルーター&lt;br /&gt;
*ルート定義不要、フォルダ階層に準じてリクエストパスとコンポーネント(.jsファイル)との対応関係が決まる&lt;br /&gt;
*page.jsはファイル名も固定でフォルダー構造だけでリクエストパスが決定される&lt;br /&gt;
&lt;br /&gt;
=====アプリ共通の外枠=====&lt;br /&gt;
*layout.js&lt;br /&gt;
*&amp;amp;lt;html&amp;amp;gt;、&amp;amp;lt;body&amp;amp;gt; 要素が存在し、個々のページを埋め込むため chilrenプロパティを引用していることが条件&lt;br /&gt;
&lt;br /&gt;
===ルートパラメータ===&lt;br /&gt;
*[名前] ： 単一パラメータ&lt;br /&gt;
*[...名前] : キャッチオールセグメント&lt;br /&gt;
*&amp;lt;nowiki&amp;gt;[[...名前]]&amp;lt;/nowiki&amp;gt; : 省略可能なキャッチオールセグメント&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ App Routerのルートパラメータ&lt;br /&gt;
|-&lt;br /&gt;
! フォルダ階層 !! 対応リクエスト !! パラメータ&lt;br /&gt;
|-&lt;br /&gt;
| /app/hoge/[id]/page.js || /hoge/001 || { id : '001' }&lt;br /&gt;
|-&lt;br /&gt;
| /app/foo/[...keys]/page.js || /foo/aaa/bbb || { keys: ['aaa', 'bbb'] }&lt;br /&gt;
|-&lt;br /&gt;
| /app/bar/&amp;lt;nowiki&amp;gt;[[...keys]]&amp;lt;/nowiki&amp;gt;/page.js || /bar || {}&lt;br /&gt;
|-&lt;br /&gt;
| 〃 || /bar/aaa/bbb || { keys: ['aaa', 'bbb'] }&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Tailwind CSS==&lt;br /&gt;
*https://tailwindcss.com/&lt;br /&gt;
*ユーティリティファーストをコンセプトに開発されたCSSフレームワーク&lt;br /&gt;
*ユーティリティを組み合わせてデザインを作るので独自のスタイルを作りやすく細かな調整もしやすいメリット&lt;br /&gt;
*標準のサイズ、カラーなどは用意されている&lt;br /&gt;
&lt;br /&gt;
[https://tailwindcsscheatsheet.com/ Cheat Sheet]&lt;br /&gt;
&lt;br /&gt;
*Tailwind　CSSによるスタイルを適用&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import &amp;quot;./globals.css&amp;quot;;&lt;br /&gt;
    :&lt;br /&gt;
&lt;br /&gt;
&amp;amp;lt;ul className=&amp;quot;fle bg-blue-600 mb-4 pl-2&amp;quot;&amp;amp;gt;...&amp;amp;lt;/ul&amp;amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Prisma==&lt;br /&gt;
*JavaScriptアプリからデータベース操作を取り持つO/Rマッパー&lt;br /&gt;
===インストール===&lt;br /&gt;
*成功すると以下のファイルが生成される&lt;br /&gt;
**.env : 環境変数ファイル、gitignore に追加する&lt;br /&gt;
** prisma/schema.prisma : Prismaのスキーマファイル&lt;br /&gt;
&lt;br /&gt;
sqliteでの構成例&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ npm install prisma --save-dev&lt;br /&gt;
 $ npx prisma init --datasource-provider sqlite&lt;br /&gt;
 warn You already have a .gitignore file. Don't forget to add `.env` in it to not commit any private information.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===データモデルの定義===&lt;br /&gt;
*prisma/schema.prisma に追記&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
model　reviews {&lt;br /&gt;
  id          String @id&lt;br /&gt;
  title       String&lt;br /&gt;
  author      String&lt;br /&gt;
  price       Int&lt;br /&gt;
  publlisher  String&lt;br /&gt;
  published   String&lt;br /&gt;
  image       String&lt;br /&gt;
  read        DateTime  @default(now())&lt;br /&gt;
  memo        String&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*DBに反映&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ npx prisma db push&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Prisma Studio(Webベース管理ツール)で確認&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ npx prisma studio&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Error: @prisma/client did not initialize yet. Please run &amp;quot;prisma generate&amp;quot; and try to import it again.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ nps prisma generate&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import { PrismaClient } from &amp;quot;@prisma/client&amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Prisma Clientの利用&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import { PrismaClient } from &amp;quot;@prisma/client&amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==サーバーアクション==&lt;br /&gt;
*Next.js内蔵の仕組み&lt;br /&gt;
*ページコンポーネント、イベントハンドラー、&amp;amp;lt;form&amp;amp;lt;要素のaction属性などからサーバーコードを呼び出す仕組み&lt;br /&gt;
*サーバーとのやりとりに際し、fetchなどの非同期通信コードの不要となり、例えばコンポーネントからデータベースを操作するにも直感的なコードを記述できる&lt;br /&gt;
*現時点ではα版&lt;br /&gt;
&lt;br /&gt;
===有効化===&lt;br /&gt;
&lt;br /&gt;
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]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
const nextConfig = {&lt;br /&gt;
    experimental: {&lt;br /&gt;
        serverActions: true&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=コンポーネントの処理=&lt;br /&gt;
*https://qiita.com/keitaMax/items/b74ef76171224c2587c4#:~:text=React%20Serv&lt;br /&gt;
&lt;br /&gt;
==サーバー側で実行==&lt;br /&gt;
*Next.jsの基本はサーバー側でコンポーネントを処理&lt;br /&gt;
*メリット&lt;br /&gt;
**サーバーリソースの活用&lt;br /&gt;
**ダウンロードコードサイズの最小化&lt;br /&gt;
**機密情報(サクセストークンなど)の管理&lt;br /&gt;
*クライアントに依存する操作には対応していない&lt;br /&gt;
**State関連操作(useState,useReducer,useEffectなど)&lt;br /&gt;
**イベントリスナー(onXxxxx)&lt;br /&gt;
**ブラウザAPIアクセス&lt;br /&gt;
**上記を伴うカスタムフック&lt;br /&gt;
**クラスコンポーネント利用&lt;br /&gt;
&lt;br /&gt;
==クライアント側で実行==&lt;br /&gt;
*ファイルの先頭に、'use client'ディレクティブを記述することでコンポーネントをクライアント側で実行可&lt;br /&gt;
&lt;br /&gt;
=実装=&lt;br /&gt;
&lt;br /&gt;
==ルートレイアウト==&lt;br /&gt;
===アプリ内のリンクにはLinkコンポーネントを利用===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import Link from &amp;quot;next/link&amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
規定で以下のようなコンポーネントが用意されており、アプリ内リソースを効率的に利用できる&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ コンポーネント&lt;br /&gt;
|-&lt;br /&gt;
! コンポーネント !! 概要&lt;br /&gt;
|-&lt;br /&gt;
| &amp;amp;lt;Link&amp;amp;gt; || リンクを生成&lt;br /&gt;
|-&lt;br /&gt;
| &amp;amp;lt;Script&amp;amp;gt; || スクリプトのロード&lt;br /&gt;
|-&lt;br /&gt;
| &amp;amp;lt;Image&amp;amp;gt; || 画像を表示&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===メタデータ===&lt;br /&gt;
*メタデータを定義しておくことで、個々のページに適切なヘッダーなどを埋め込める&lt;br /&gt;
*複数箇所で宣言された場合、シャローマージされる&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
export const metadata: Metadata = {&lt;br /&gt;
  title: &amp;quot;Reading Recorder&amp;quot;,&lt;br /&gt;
  description: &amp;quot;自分が読んだ書籍の記録を残す&amp;quot;,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*generateMetadata関数を利用しデータベースなどから取得した結果を元に動的に生成も可能&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
export async function generateMetadata({ params, searchParams }) {&lt;br /&gt;
    :&lt;br /&gt;
    return {&lt;br /&gt;
        title : result.title,&lt;br /&gt;
            :&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Route Segment Config===&lt;br /&gt;
*レイアウト、ページ単位の設定 &lt;br /&gt;
*あらかじめ決められた名前の変数をエクスポートしておくことで、個別の設定を施せる&lt;br /&gt;
*force-dynamic : 極力キャッシュを無効にし、ページを動的に描画しようとする&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
export const dynamic = 'force-dynamic'&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=フォント=&lt;br /&gt;
*Googleフォント(無償フォントのディレクトリサービス)を有効化&lt;br /&gt;
*具体的なフォントはGoogleフォントから自由に選択できるが一般的にはバリアブルフォント推奨(下例ではInconsolata)&lt;br /&gt;
*フォントはファイルサイズが大きいので、subsetで利用する文字のみ取り出す&lt;br /&gt;
*fnc.className でフォントを適用できる&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import { Inconsolata } from 'next/font/google';&lt;br /&gt;
const fnt = Inconsolata({ subsets: ['latin'] });&lt;br /&gt;
&lt;br /&gt;
  :&lt;br /&gt;
&amp;amp;lt;body className={`${fnt.className}` }&amp;amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=MUI=&lt;br /&gt;
[[MUI]]&lt;br /&gt;
&lt;br /&gt;
=Tips=&lt;br /&gt;
&lt;br /&gt;
==リモートホストからの画像表示を許可する==&lt;br /&gt;
*next.config.mjs&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
const nextConfig = {&lt;br /&gt;
&lt;br /&gt;
    :&lt;br /&gt;
&lt;br /&gt;
    images: {&lt;br /&gt;
        remotePatterns: [&lt;br /&gt;
            {&lt;br /&gt;
                hostname: 'books.google.com'&lt;br /&gt;
            } &lt;br /&gt;
        ] &lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Piroto</name></author>
		
	</entry>
	<entry>
		<id>https://www.typea.info/tips_/index.php?title=Next.js&amp;diff=35343</id>
		<title>Next.js</title>
		<link rel="alternate" type="text/html" href="https://www.typea.info/tips_/index.php?title=Next.js&amp;diff=35343"/>
		<updated>2024-10-05T15:34:43Z</updated>

		<summary type="html">&lt;p&gt;Piroto: /* メタデータ */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[React]] | [[MUI]] |&lt;br /&gt;
&lt;br /&gt;
{{amazon|4815619484}}&lt;br /&gt;
&lt;br /&gt;
=概要=&lt;br /&gt;
*Reactは、あくまでUI部分のみ&lt;br /&gt;
*本格的なアプリ開発には周辺領域を担うためのフレームワークが必要&lt;br /&gt;
*Reactベースのフレームワークとしてデファクトスタンダードと言える存在&lt;br /&gt;
*主なライブラリ&lt;br /&gt;
**ファイルシステムベースの設定レスルーター&lt;br /&gt;
**サーバーコンポーネント&lt;br /&gt;
**データ取得用fetchメソッド&lt;br /&gt;
**リソース組み込みの自動最適化&lt;br /&gt;
**CSSフレームワーク、Tailwind　CSSへの標準対応&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=導入=&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
newdelhi:Workspaces piroto$ npx create-next-app@latest&lt;br /&gt;
Need to install the following packages:&lt;br /&gt;
create-next-app@14.2.14&lt;br /&gt;
Ok to proceed? (y) y&lt;br /&gt;
&lt;br /&gt;
✔ What is your project named? … first-nextjs-app&lt;br /&gt;
✔ Would you like to use TypeScript? … No / Yes&lt;br /&gt;
✔ Would you like to use ESLint? … No / Yes&lt;br /&gt;
✔ Would you like to use Tailwind CSS? … No / Yes&lt;br /&gt;
✔ Would you like to use `src/` directory? … No / Yes&lt;br /&gt;
✔ Would you like to use App Router? (recommended) … No / Yes&lt;br /&gt;
✔ Would you like to customize the default import alias (@/*)? … No / Yes&lt;br /&gt;
Creating a new Next.js app in /Users/piroto/Workspaces/first-nextjs-app.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==実行==&lt;br /&gt;
===開発===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
npm run dev&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Start_next_js.png | 300px]]&lt;br /&gt;
&lt;br /&gt;
===本番ビルド＋実行===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
npm run build&lt;br /&gt;
npm start&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==App Router==&lt;br /&gt;
*React Routerとは異なる独自のルーターを標準で提供&lt;br /&gt;
*コンポーネントそのものはReactと変わらない&lt;br /&gt;
&lt;br /&gt;
===2種類のルーター===&lt;br /&gt;
&lt;br /&gt;
*Pages Router : 旧来から提供されている&lt;br /&gt;
*App Router : Next.js 13から導入された新しいルーター(推奨)&lt;br /&gt;
&lt;br /&gt;
====App Router====&lt;br /&gt;
*フォルダベースのルーター&lt;br /&gt;
*ルート定義不要、フォルダ階層に準じてリクエストパスとコンポーネント(.jsファイル)との対応関係が決まる&lt;br /&gt;
*page.jsはファイル名も固定でフォルダー構造だけでリクエストパスが決定される&lt;br /&gt;
&lt;br /&gt;
=====アプリ共通の外枠=====&lt;br /&gt;
*layout.js&lt;br /&gt;
*&amp;amp;lt;html&amp;amp;gt;、&amp;amp;lt;body&amp;amp;gt; 要素が存在し、個々のページを埋め込むため chilrenプロパティを引用していることが条件&lt;br /&gt;
&lt;br /&gt;
===ルートパラメータ===&lt;br /&gt;
*[名前] ： 単一パラメータ&lt;br /&gt;
*[...名前] : キャッチオールセグメント&lt;br /&gt;
*&amp;lt;nowiki&amp;gt;[[...名前]]&amp;lt;/nowiki&amp;gt; : 省略可能なキャッチオールセグメント&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ App Routerのルートパラメータ&lt;br /&gt;
|-&lt;br /&gt;
! フォルダ階層 !! 対応リクエスト !! パラメータ&lt;br /&gt;
|-&lt;br /&gt;
| /app/hoge/[id]/page.js || /hoge/001 || { id : '001' }&lt;br /&gt;
|-&lt;br /&gt;
| /app/foo/[...keys]/page.js || /foo/aaa/bbb || { keys: ['aaa', 'bbb'] }&lt;br /&gt;
|-&lt;br /&gt;
| /app/bar/&amp;lt;nowiki&amp;gt;[[...keys]]&amp;lt;/nowiki&amp;gt;/page.js || /bar || {}&lt;br /&gt;
|-&lt;br /&gt;
| 〃 || /bar/aaa/bbb || { keys: ['aaa', 'bbb'] }&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Tailwind CSS==&lt;br /&gt;
*https://tailwindcss.com/&lt;br /&gt;
*ユーティリティファーストをコンセプトに開発されたCSSフレームワーク&lt;br /&gt;
*ユーティリティを組み合わせてデザインを作るので独自のスタイルを作りやすく細かな調整もしやすいメリット&lt;br /&gt;
*標準のサイズ、カラーなどは用意されている&lt;br /&gt;
&lt;br /&gt;
[https://tailwindcsscheatsheet.com/ Cheat Sheet]&lt;br /&gt;
&lt;br /&gt;
*Tailwind　CSSによるスタイルを適用&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import &amp;quot;./globals.css&amp;quot;;&lt;br /&gt;
    :&lt;br /&gt;
&lt;br /&gt;
&amp;amp;lt;ul className=&amp;quot;fle bg-blue-600 mb-4 pl-2&amp;quot;&amp;amp;gt;...&amp;amp;lt;/ul&amp;amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Prisma==&lt;br /&gt;
*JavaScriptアプリからデータベース操作を取り持つO/Rマッパー&lt;br /&gt;
===インストール===&lt;br /&gt;
*成功すると以下のファイルが生成される&lt;br /&gt;
**.env : 環境変数ファイル、gitignore に追加する&lt;br /&gt;
** prisma/schema.prisma : Prismaのスキーマファイル&lt;br /&gt;
&lt;br /&gt;
sqliteでの構成例&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ npm install prisma --save-dev&lt;br /&gt;
 $ npx prisma init --datasource-provider sqlite&lt;br /&gt;
 warn You already have a .gitignore file. Don't forget to add `.env` in it to not commit any private information.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===データモデルの定義===&lt;br /&gt;
*prisma/schema.prisma に追記&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
model　reviews {&lt;br /&gt;
  id          String @id&lt;br /&gt;
  title       String&lt;br /&gt;
  author      String&lt;br /&gt;
  price       Int&lt;br /&gt;
  publlisher  String&lt;br /&gt;
  published   String&lt;br /&gt;
  image       String&lt;br /&gt;
  read        DateTime  @default(now())&lt;br /&gt;
  memo        String&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*DBに反映&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ npx prisma db push&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Prisma Studio(Webベース管理ツール)で確認&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ npx prisma studio&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Error: @prisma/client did not initialize yet. Please run &amp;quot;prisma generate&amp;quot; and try to import it again.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ nps prisma generate&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import { PrismaClient } from &amp;quot;@prisma/client&amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Prisma Clientの利用&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import { PrismaClient } from &amp;quot;@prisma/client&amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==サーバーアクション==&lt;br /&gt;
*Next.js内蔵の仕組み&lt;br /&gt;
*ページコンポーネント、イベントハンドラー、&amp;amp;lt;form&amp;amp;lt;要素のaction属性などからサーバーコードを呼び出す仕組み&lt;br /&gt;
*サーバーとのやりとりに際し、fetchなどの非同期通信コードの不要となり、例えばコンポーネントからデータベースを操作するにも直感的なコードを記述できる&lt;br /&gt;
*現時点ではα版&lt;br /&gt;
&lt;br /&gt;
===有効化===&lt;br /&gt;
&lt;br /&gt;
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]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
const nextConfig = {&lt;br /&gt;
    experimental: {&lt;br /&gt;
        serverActions: true&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=サーバーコンポーネント=&lt;br /&gt;
*https://qiita.com/keitaMax/items/b74ef76171224c2587c4#:~:text=React%20Serv&lt;br /&gt;
&lt;br /&gt;
*Next.jsの基本はサーバーコンポーネント&lt;br /&gt;
*ファイルの先頭に、'use client'、'use server'ディレクティブを記述する&lt;br /&gt;
&lt;br /&gt;
=実装=&lt;br /&gt;
&lt;br /&gt;
==ルートレイアウト==&lt;br /&gt;
===アプリ内のリンクにはLinkコンポーネントを利用===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import Link from &amp;quot;next/link&amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
規定で以下のようなコンポーネントが用意されており、アプリ内リソースを効率的に利用できる&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ コンポーネント&lt;br /&gt;
|-&lt;br /&gt;
! コンポーネント !! 概要&lt;br /&gt;
|-&lt;br /&gt;
| &amp;amp;lt;Link&amp;amp;gt; || リンクを生成&lt;br /&gt;
|-&lt;br /&gt;
| &amp;amp;lt;Script&amp;amp;gt; || スクリプトのロード&lt;br /&gt;
|-&lt;br /&gt;
| &amp;amp;lt;Image&amp;amp;gt; || 画像を表示&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===メタデータ===&lt;br /&gt;
*メタデータを定義しておくことで、個々のページに適切なヘッダーなどを埋め込める&lt;br /&gt;
*複数箇所で宣言された場合、シャローマージされる&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
export const metadata: Metadata = {&lt;br /&gt;
  title: &amp;quot;Reading Recorder&amp;quot;,&lt;br /&gt;
  description: &amp;quot;自分が読んだ書籍の記録を残す&amp;quot;,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*generateMetadata関数を利用しデータベースなどから取得した結果を元に動的に生成も可能&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
export async function generateMetadata({ params, searchParams }) {&lt;br /&gt;
    :&lt;br /&gt;
    return {&lt;br /&gt;
        title : result.title,&lt;br /&gt;
            :&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Route Segment Config===&lt;br /&gt;
*レイアウト、ページ単位の設定 &lt;br /&gt;
*あらかじめ決められた名前の変数をエクスポートしておくことで、個別の設定を施せる&lt;br /&gt;
*force-dynamic : 極力キャッシュを無効にし、ページを動的に描画しようとする&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
export const dynamic = 'force-dynamic'&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=フォント=&lt;br /&gt;
*Googleフォント(無償フォントのディレクトリサービス)を有効化&lt;br /&gt;
*具体的なフォントはGoogleフォントから自由に選択できるが一般的にはバリアブルフォント推奨(下例ではInconsolata)&lt;br /&gt;
*フォントはファイルサイズが大きいので、subsetで利用する文字のみ取り出す&lt;br /&gt;
*fnc.className でフォントを適用できる&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import { Inconsolata } from 'next/font/google';&lt;br /&gt;
const fnt = Inconsolata({ subsets: ['latin'] });&lt;br /&gt;
&lt;br /&gt;
  :&lt;br /&gt;
&amp;amp;lt;body className={`${fnt.className}` }&amp;amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=MUI=&lt;br /&gt;
[[MUI]]&lt;br /&gt;
&lt;br /&gt;
=Tips=&lt;br /&gt;
&lt;br /&gt;
==リモートホストからの画像表示を許可する==&lt;br /&gt;
*next.config.mjs&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
const nextConfig = {&lt;br /&gt;
&lt;br /&gt;
    :&lt;br /&gt;
&lt;br /&gt;
    images: {&lt;br /&gt;
        remotePatterns: [&lt;br /&gt;
            {&lt;br /&gt;
                hostname: 'books.google.com'&lt;br /&gt;
            } &lt;br /&gt;
        ] &lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Piroto</name></author>
		
	</entry>
	<entry>
		<id>https://www.typea.info/tips_/index.php?title=Next.js&amp;diff=35342</id>
		<title>Next.js</title>
		<link rel="alternate" type="text/html" href="https://www.typea.info/tips_/index.php?title=Next.js&amp;diff=35342"/>
		<updated>2024-10-05T15:21:55Z</updated>

		<summary type="html">&lt;p&gt;Piroto: /* サーバーコンポーネント */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[React]] | [[MUI]] |&lt;br /&gt;
&lt;br /&gt;
{{amazon|4815619484}}&lt;br /&gt;
&lt;br /&gt;
=概要=&lt;br /&gt;
*Reactは、あくまでUI部分のみ&lt;br /&gt;
*本格的なアプリ開発には周辺領域を担うためのフレームワークが必要&lt;br /&gt;
*Reactベースのフレームワークとしてデファクトスタンダードと言える存在&lt;br /&gt;
*主なライブラリ&lt;br /&gt;
**ファイルシステムベースの設定レスルーター&lt;br /&gt;
**サーバーコンポーネント&lt;br /&gt;
**データ取得用fetchメソッド&lt;br /&gt;
**リソース組み込みの自動最適化&lt;br /&gt;
**CSSフレームワーク、Tailwind　CSSへの標準対応&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=導入=&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
newdelhi:Workspaces piroto$ npx create-next-app@latest&lt;br /&gt;
Need to install the following packages:&lt;br /&gt;
create-next-app@14.2.14&lt;br /&gt;
Ok to proceed? (y) y&lt;br /&gt;
&lt;br /&gt;
✔ What is your project named? … first-nextjs-app&lt;br /&gt;
✔ Would you like to use TypeScript? … No / Yes&lt;br /&gt;
✔ Would you like to use ESLint? … No / Yes&lt;br /&gt;
✔ Would you like to use Tailwind CSS? … No / Yes&lt;br /&gt;
✔ Would you like to use `src/` directory? … No / Yes&lt;br /&gt;
✔ Would you like to use App Router? (recommended) … No / Yes&lt;br /&gt;
✔ Would you like to customize the default import alias (@/*)? … No / Yes&lt;br /&gt;
Creating a new Next.js app in /Users/piroto/Workspaces/first-nextjs-app.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==実行==&lt;br /&gt;
===開発===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
npm run dev&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Start_next_js.png | 300px]]&lt;br /&gt;
&lt;br /&gt;
===本番ビルド＋実行===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
npm run build&lt;br /&gt;
npm start&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==App Router==&lt;br /&gt;
*React Routerとは異なる独自のルーターを標準で提供&lt;br /&gt;
*コンポーネントそのものはReactと変わらない&lt;br /&gt;
&lt;br /&gt;
===2種類のルーター===&lt;br /&gt;
&lt;br /&gt;
*Pages Router : 旧来から提供されている&lt;br /&gt;
*App Router : Next.js 13から導入された新しいルーター(推奨)&lt;br /&gt;
&lt;br /&gt;
====App Router====&lt;br /&gt;
*フォルダベースのルーター&lt;br /&gt;
*ルート定義不要、フォルダ階層に準じてリクエストパスとコンポーネント(.jsファイル)との対応関係が決まる&lt;br /&gt;
*page.jsはファイル名も固定でフォルダー構造だけでリクエストパスが決定される&lt;br /&gt;
&lt;br /&gt;
=====アプリ共通の外枠=====&lt;br /&gt;
*layout.js&lt;br /&gt;
*&amp;amp;lt;html&amp;amp;gt;、&amp;amp;lt;body&amp;amp;gt; 要素が存在し、個々のページを埋め込むため chilrenプロパティを引用していることが条件&lt;br /&gt;
&lt;br /&gt;
===ルートパラメータ===&lt;br /&gt;
*[名前] ： 単一パラメータ&lt;br /&gt;
*[...名前] : キャッチオールセグメント&lt;br /&gt;
*&amp;lt;nowiki&amp;gt;[[...名前]]&amp;lt;/nowiki&amp;gt; : 省略可能なキャッチオールセグメント&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ App Routerのルートパラメータ&lt;br /&gt;
|-&lt;br /&gt;
! フォルダ階層 !! 対応リクエスト !! パラメータ&lt;br /&gt;
|-&lt;br /&gt;
| /app/hoge/[id]/page.js || /hoge/001 || { id : '001' }&lt;br /&gt;
|-&lt;br /&gt;
| /app/foo/[...keys]/page.js || /foo/aaa/bbb || { keys: ['aaa', 'bbb'] }&lt;br /&gt;
|-&lt;br /&gt;
| /app/bar/&amp;lt;nowiki&amp;gt;[[...keys]]&amp;lt;/nowiki&amp;gt;/page.js || /bar || {}&lt;br /&gt;
|-&lt;br /&gt;
| 〃 || /bar/aaa/bbb || { keys: ['aaa', 'bbb'] }&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Tailwind CSS==&lt;br /&gt;
*https://tailwindcss.com/&lt;br /&gt;
*ユーティリティファーストをコンセプトに開発されたCSSフレームワーク&lt;br /&gt;
*ユーティリティを組み合わせてデザインを作るので独自のスタイルを作りやすく細かな調整もしやすいメリット&lt;br /&gt;
*標準のサイズ、カラーなどは用意されている&lt;br /&gt;
&lt;br /&gt;
[https://tailwindcsscheatsheet.com/ Cheat Sheet]&lt;br /&gt;
&lt;br /&gt;
*Tailwind　CSSによるスタイルを適用&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import &amp;quot;./globals.css&amp;quot;;&lt;br /&gt;
    :&lt;br /&gt;
&lt;br /&gt;
&amp;amp;lt;ul className=&amp;quot;fle bg-blue-600 mb-4 pl-2&amp;quot;&amp;amp;gt;...&amp;amp;lt;/ul&amp;amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Prisma==&lt;br /&gt;
*JavaScriptアプリからデータベース操作を取り持つO/Rマッパー&lt;br /&gt;
===インストール===&lt;br /&gt;
*成功すると以下のファイルが生成される&lt;br /&gt;
**.env : 環境変数ファイル、gitignore に追加する&lt;br /&gt;
** prisma/schema.prisma : Prismaのスキーマファイル&lt;br /&gt;
&lt;br /&gt;
sqliteでの構成例&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ npm install prisma --save-dev&lt;br /&gt;
 $ npx prisma init --datasource-provider sqlite&lt;br /&gt;
 warn You already have a .gitignore file. Don't forget to add `.env` in it to not commit any private information.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===データモデルの定義===&lt;br /&gt;
*prisma/schema.prisma に追記&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
model　reviews {&lt;br /&gt;
  id          String @id&lt;br /&gt;
  title       String&lt;br /&gt;
  author      String&lt;br /&gt;
  price       Int&lt;br /&gt;
  publlisher  String&lt;br /&gt;
  published   String&lt;br /&gt;
  image       String&lt;br /&gt;
  read        DateTime  @default(now())&lt;br /&gt;
  memo        String&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*DBに反映&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ npx prisma db push&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Prisma Studio(Webベース管理ツール)で確認&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ npx prisma studio&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Error: @prisma/client did not initialize yet. Please run &amp;quot;prisma generate&amp;quot; and try to import it again.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ nps prisma generate&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import { PrismaClient } from &amp;quot;@prisma/client&amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Prisma Clientの利用&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import { PrismaClient } from &amp;quot;@prisma/client&amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==サーバーアクション==&lt;br /&gt;
*Next.js内蔵の仕組み&lt;br /&gt;
*ページコンポーネント、イベントハンドラー、&amp;amp;lt;form&amp;amp;lt;要素のaction属性などからサーバーコードを呼び出す仕組み&lt;br /&gt;
*サーバーとのやりとりに際し、fetchなどの非同期通信コードの不要となり、例えばコンポーネントからデータベースを操作するにも直感的なコードを記述できる&lt;br /&gt;
*現時点ではα版&lt;br /&gt;
&lt;br /&gt;
===有効化===&lt;br /&gt;
&lt;br /&gt;
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]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
const nextConfig = {&lt;br /&gt;
    experimental: {&lt;br /&gt;
        serverActions: true&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=サーバーコンポーネント=&lt;br /&gt;
*https://qiita.com/keitaMax/items/b74ef76171224c2587c4#:~:text=React%20Serv&lt;br /&gt;
&lt;br /&gt;
*Next.jsの基本はサーバーコンポーネント&lt;br /&gt;
*ファイルの先頭に、'use client'、'use server'ディレクティブを記述する&lt;br /&gt;
&lt;br /&gt;
=実装=&lt;br /&gt;
&lt;br /&gt;
==ルートレイアウト==&lt;br /&gt;
===アプリ内のリンクにはLinkコンポーネントを利用===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import Link from &amp;quot;next/link&amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
規定で以下のようなコンポーネントが用意されており、アプリ内リソースを効率的に利用できる&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ コンポーネント&lt;br /&gt;
|-&lt;br /&gt;
! コンポーネント !! 概要&lt;br /&gt;
|-&lt;br /&gt;
| &amp;amp;lt;Link&amp;amp;gt; || リンクを生成&lt;br /&gt;
|-&lt;br /&gt;
| &amp;amp;lt;Script&amp;amp;gt; || スクリプトのロード&lt;br /&gt;
|-&lt;br /&gt;
| &amp;amp;lt;Image&amp;amp;gt; || 画像を表示&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===メタデータ===&lt;br /&gt;
*メタデータを定義しておくことで、個々のページに適切なヘッダーなどを埋め込める&lt;br /&gt;
*複数箇所で宣言された場合、シャローマージされる&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
export const metadata: Metadata = {&lt;br /&gt;
  title: &amp;quot;Reading Recorder&amp;quot;,&lt;br /&gt;
  description: &amp;quot;自分が読んだ書籍の記録を残す&amp;quot;,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*generateMetadata関数を利用しデータベースなどから取得した結果を元に動的に生成も可能&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
export async function generateMetadata({ params, searchParams }) {&lt;br /&gt;
    :&lt;br /&gt;
    return {&lt;br /&gt;
        title : result.title,&lt;br /&gt;
            :&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=フォント=&lt;br /&gt;
*Googleフォント(無償フォントのディレクトリサービス)を有効化&lt;br /&gt;
*具体的なフォントはGoogleフォントから自由に選択できるが一般的にはバリアブルフォント推奨(下例ではInconsolata)&lt;br /&gt;
*フォントはファイルサイズが大きいので、subsetで利用する文字のみ取り出す&lt;br /&gt;
*fnc.className でフォントを適用できる&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import { Inconsolata } from 'next/font/google';&lt;br /&gt;
const fnt = Inconsolata({ subsets: ['latin'] });&lt;br /&gt;
&lt;br /&gt;
  :&lt;br /&gt;
&amp;amp;lt;body className={`${fnt.className}` }&amp;amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=MUI=&lt;br /&gt;
[[MUI]]&lt;br /&gt;
&lt;br /&gt;
=Tips=&lt;br /&gt;
&lt;br /&gt;
==リモートホストからの画像表示を許可する==&lt;br /&gt;
*next.config.mjs&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
const nextConfig = {&lt;br /&gt;
&lt;br /&gt;
    :&lt;br /&gt;
&lt;br /&gt;
    images: {&lt;br /&gt;
        remotePatterns: [&lt;br /&gt;
            {&lt;br /&gt;
                hostname: 'books.google.com'&lt;br /&gt;
            } &lt;br /&gt;
        ] &lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Piroto</name></author>
		
	</entry>
	<entry>
		<id>https://www.typea.info/tips_/index.php?title=Next.js&amp;diff=35341</id>
		<title>Next.js</title>
		<link rel="alternate" type="text/html" href="https://www.typea.info/tips_/index.php?title=Next.js&amp;diff=35341"/>
		<updated>2024-10-05T15:20:24Z</updated>

		<summary type="html">&lt;p&gt;Piroto: /* サーバーコンポーネント */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[React]] | [[MUI]] |&lt;br /&gt;
&lt;br /&gt;
{{amazon|4815619484}}&lt;br /&gt;
&lt;br /&gt;
=概要=&lt;br /&gt;
*Reactは、あくまでUI部分のみ&lt;br /&gt;
*本格的なアプリ開発には周辺領域を担うためのフレームワークが必要&lt;br /&gt;
*Reactベースのフレームワークとしてデファクトスタンダードと言える存在&lt;br /&gt;
*主なライブラリ&lt;br /&gt;
**ファイルシステムベースの設定レスルーター&lt;br /&gt;
**サーバーコンポーネント&lt;br /&gt;
**データ取得用fetchメソッド&lt;br /&gt;
**リソース組み込みの自動最適化&lt;br /&gt;
**CSSフレームワーク、Tailwind　CSSへの標準対応&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=導入=&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
newdelhi:Workspaces piroto$ npx create-next-app@latest&lt;br /&gt;
Need to install the following packages:&lt;br /&gt;
create-next-app@14.2.14&lt;br /&gt;
Ok to proceed? (y) y&lt;br /&gt;
&lt;br /&gt;
✔ What is your project named? … first-nextjs-app&lt;br /&gt;
✔ Would you like to use TypeScript? … No / Yes&lt;br /&gt;
✔ Would you like to use ESLint? … No / Yes&lt;br /&gt;
✔ Would you like to use Tailwind CSS? … No / Yes&lt;br /&gt;
✔ Would you like to use `src/` directory? … No / Yes&lt;br /&gt;
✔ Would you like to use App Router? (recommended) … No / Yes&lt;br /&gt;
✔ Would you like to customize the default import alias (@/*)? … No / Yes&lt;br /&gt;
Creating a new Next.js app in /Users/piroto/Workspaces/first-nextjs-app.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==実行==&lt;br /&gt;
===開発===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
npm run dev&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Start_next_js.png | 300px]]&lt;br /&gt;
&lt;br /&gt;
===本番ビルド＋実行===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
npm run build&lt;br /&gt;
npm start&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==App Router==&lt;br /&gt;
*React Routerとは異なる独自のルーターを標準で提供&lt;br /&gt;
*コンポーネントそのものはReactと変わらない&lt;br /&gt;
&lt;br /&gt;
===2種類のルーター===&lt;br /&gt;
&lt;br /&gt;
*Pages Router : 旧来から提供されている&lt;br /&gt;
*App Router : Next.js 13から導入された新しいルーター(推奨)&lt;br /&gt;
&lt;br /&gt;
====App Router====&lt;br /&gt;
*フォルダベースのルーター&lt;br /&gt;
*ルート定義不要、フォルダ階層に準じてリクエストパスとコンポーネント(.jsファイル)との対応関係が決まる&lt;br /&gt;
*page.jsはファイル名も固定でフォルダー構造だけでリクエストパスが決定される&lt;br /&gt;
&lt;br /&gt;
=====アプリ共通の外枠=====&lt;br /&gt;
*layout.js&lt;br /&gt;
*&amp;amp;lt;html&amp;amp;gt;、&amp;amp;lt;body&amp;amp;gt; 要素が存在し、個々のページを埋め込むため chilrenプロパティを引用していることが条件&lt;br /&gt;
&lt;br /&gt;
===ルートパラメータ===&lt;br /&gt;
*[名前] ： 単一パラメータ&lt;br /&gt;
*[...名前] : キャッチオールセグメント&lt;br /&gt;
*&amp;lt;nowiki&amp;gt;[[...名前]]&amp;lt;/nowiki&amp;gt; : 省略可能なキャッチオールセグメント&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ App Routerのルートパラメータ&lt;br /&gt;
|-&lt;br /&gt;
! フォルダ階層 !! 対応リクエスト !! パラメータ&lt;br /&gt;
|-&lt;br /&gt;
| /app/hoge/[id]/page.js || /hoge/001 || { id : '001' }&lt;br /&gt;
|-&lt;br /&gt;
| /app/foo/[...keys]/page.js || /foo/aaa/bbb || { keys: ['aaa', 'bbb'] }&lt;br /&gt;
|-&lt;br /&gt;
| /app/bar/&amp;lt;nowiki&amp;gt;[[...keys]]&amp;lt;/nowiki&amp;gt;/page.js || /bar || {}&lt;br /&gt;
|-&lt;br /&gt;
| 〃 || /bar/aaa/bbb || { keys: ['aaa', 'bbb'] }&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Tailwind CSS==&lt;br /&gt;
*https://tailwindcss.com/&lt;br /&gt;
*ユーティリティファーストをコンセプトに開発されたCSSフレームワーク&lt;br /&gt;
*ユーティリティを組み合わせてデザインを作るので独自のスタイルを作りやすく細かな調整もしやすいメリット&lt;br /&gt;
*標準のサイズ、カラーなどは用意されている&lt;br /&gt;
&lt;br /&gt;
[https://tailwindcsscheatsheet.com/ Cheat Sheet]&lt;br /&gt;
&lt;br /&gt;
*Tailwind　CSSによるスタイルを適用&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import &amp;quot;./globals.css&amp;quot;;&lt;br /&gt;
    :&lt;br /&gt;
&lt;br /&gt;
&amp;amp;lt;ul className=&amp;quot;fle bg-blue-600 mb-4 pl-2&amp;quot;&amp;amp;gt;...&amp;amp;lt;/ul&amp;amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Prisma==&lt;br /&gt;
*JavaScriptアプリからデータベース操作を取り持つO/Rマッパー&lt;br /&gt;
===インストール===&lt;br /&gt;
*成功すると以下のファイルが生成される&lt;br /&gt;
**.env : 環境変数ファイル、gitignore に追加する&lt;br /&gt;
** prisma/schema.prisma : Prismaのスキーマファイル&lt;br /&gt;
&lt;br /&gt;
sqliteでの構成例&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ npm install prisma --save-dev&lt;br /&gt;
 $ npx prisma init --datasource-provider sqlite&lt;br /&gt;
 warn You already have a .gitignore file. Don't forget to add `.env` in it to not commit any private information.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===データモデルの定義===&lt;br /&gt;
*prisma/schema.prisma に追記&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
model　reviews {&lt;br /&gt;
  id          String @id&lt;br /&gt;
  title       String&lt;br /&gt;
  author      String&lt;br /&gt;
  price       Int&lt;br /&gt;
  publlisher  String&lt;br /&gt;
  published   String&lt;br /&gt;
  image       String&lt;br /&gt;
  read        DateTime  @default(now())&lt;br /&gt;
  memo        String&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*DBに反映&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ npx prisma db push&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Prisma Studio(Webベース管理ツール)で確認&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ npx prisma studio&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Error: @prisma/client did not initialize yet. Please run &amp;quot;prisma generate&amp;quot; and try to import it again.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ nps prisma generate&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import { PrismaClient } from &amp;quot;@prisma/client&amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Prisma Clientの利用&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import { PrismaClient } from &amp;quot;@prisma/client&amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==サーバーアクション==&lt;br /&gt;
*Next.js内蔵の仕組み&lt;br /&gt;
*ページコンポーネント、イベントハンドラー、&amp;amp;lt;form&amp;amp;lt;要素のaction属性などからサーバーコードを呼び出す仕組み&lt;br /&gt;
*サーバーとのやりとりに際し、fetchなどの非同期通信コードの不要となり、例えばコンポーネントからデータベースを操作するにも直感的なコードを記述できる&lt;br /&gt;
*現時点ではα版&lt;br /&gt;
&lt;br /&gt;
===有効化===&lt;br /&gt;
&lt;br /&gt;
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]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
const nextConfig = {&lt;br /&gt;
    experimental: {&lt;br /&gt;
        serverActions: true&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=サーバーコンポーネント=&lt;br /&gt;
*https://qiita.com/keitaMax/items/b74ef76171224c2587c4#:~:text=React%20Serv&lt;br /&gt;
&lt;br /&gt;
*Next.jsの基本はサーバーコンポーネント&lt;br /&gt;
&lt;br /&gt;
=実装=&lt;br /&gt;
&lt;br /&gt;
==ルートレイアウト==&lt;br /&gt;
===アプリ内のリンクにはLinkコンポーネントを利用===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import Link from &amp;quot;next/link&amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
規定で以下のようなコンポーネントが用意されており、アプリ内リソースを効率的に利用できる&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ コンポーネント&lt;br /&gt;
|-&lt;br /&gt;
! コンポーネント !! 概要&lt;br /&gt;
|-&lt;br /&gt;
| &amp;amp;lt;Link&amp;amp;gt; || リンクを生成&lt;br /&gt;
|-&lt;br /&gt;
| &amp;amp;lt;Script&amp;amp;gt; || スクリプトのロード&lt;br /&gt;
|-&lt;br /&gt;
| &amp;amp;lt;Image&amp;amp;gt; || 画像を表示&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===メタデータ===&lt;br /&gt;
*メタデータを定義しておくことで、個々のページに適切なヘッダーなどを埋め込める&lt;br /&gt;
*複数箇所で宣言された場合、シャローマージされる&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
export const metadata: Metadata = {&lt;br /&gt;
  title: &amp;quot;Reading Recorder&amp;quot;,&lt;br /&gt;
  description: &amp;quot;自分が読んだ書籍の記録を残す&amp;quot;,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*generateMetadata関数を利用しデータベースなどから取得した結果を元に動的に生成も可能&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
export async function generateMetadata({ params, searchParams }) {&lt;br /&gt;
    :&lt;br /&gt;
    return {&lt;br /&gt;
        title : result.title,&lt;br /&gt;
            :&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=フォント=&lt;br /&gt;
*Googleフォント(無償フォントのディレクトリサービス)を有効化&lt;br /&gt;
*具体的なフォントはGoogleフォントから自由に選択できるが一般的にはバリアブルフォント推奨(下例ではInconsolata)&lt;br /&gt;
*フォントはファイルサイズが大きいので、subsetで利用する文字のみ取り出す&lt;br /&gt;
*fnc.className でフォントを適用できる&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import { Inconsolata } from 'next/font/google';&lt;br /&gt;
const fnt = Inconsolata({ subsets: ['latin'] });&lt;br /&gt;
&lt;br /&gt;
  :&lt;br /&gt;
&amp;amp;lt;body className={`${fnt.className}` }&amp;amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=MUI=&lt;br /&gt;
[[MUI]]&lt;br /&gt;
&lt;br /&gt;
=Tips=&lt;br /&gt;
&lt;br /&gt;
==リモートホストからの画像表示を許可する==&lt;br /&gt;
*next.config.mjs&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
const nextConfig = {&lt;br /&gt;
&lt;br /&gt;
    :&lt;br /&gt;
&lt;br /&gt;
    images: {&lt;br /&gt;
        remotePatterns: [&lt;br /&gt;
            {&lt;br /&gt;
                hostname: 'books.google.com'&lt;br /&gt;
            } &lt;br /&gt;
        ] &lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Piroto</name></author>
		
	</entry>
	<entry>
		<id>https://www.typea.info/tips_/index.php?title=Next.js&amp;diff=35340</id>
		<title>Next.js</title>
		<link rel="alternate" type="text/html" href="https://www.typea.info/tips_/index.php?title=Next.js&amp;diff=35340"/>
		<updated>2024-10-05T15:19:28Z</updated>

		<summary type="html">&lt;p&gt;Piroto: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[React]] | [[MUI]] |&lt;br /&gt;
&lt;br /&gt;
{{amazon|4815619484}}&lt;br /&gt;
&lt;br /&gt;
=概要=&lt;br /&gt;
*Reactは、あくまでUI部分のみ&lt;br /&gt;
*本格的なアプリ開発には周辺領域を担うためのフレームワークが必要&lt;br /&gt;
*Reactベースのフレームワークとしてデファクトスタンダードと言える存在&lt;br /&gt;
*主なライブラリ&lt;br /&gt;
**ファイルシステムベースの設定レスルーター&lt;br /&gt;
**サーバーコンポーネント&lt;br /&gt;
**データ取得用fetchメソッド&lt;br /&gt;
**リソース組み込みの自動最適化&lt;br /&gt;
**CSSフレームワーク、Tailwind　CSSへの標準対応&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=導入=&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
newdelhi:Workspaces piroto$ npx create-next-app@latest&lt;br /&gt;
Need to install the following packages:&lt;br /&gt;
create-next-app@14.2.14&lt;br /&gt;
Ok to proceed? (y) y&lt;br /&gt;
&lt;br /&gt;
✔ What is your project named? … first-nextjs-app&lt;br /&gt;
✔ Would you like to use TypeScript? … No / Yes&lt;br /&gt;
✔ Would you like to use ESLint? … No / Yes&lt;br /&gt;
✔ Would you like to use Tailwind CSS? … No / Yes&lt;br /&gt;
✔ Would you like to use `src/` directory? … No / Yes&lt;br /&gt;
✔ Would you like to use App Router? (recommended) … No / Yes&lt;br /&gt;
✔ Would you like to customize the default import alias (@/*)? … No / Yes&lt;br /&gt;
Creating a new Next.js app in /Users/piroto/Workspaces/first-nextjs-app.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==実行==&lt;br /&gt;
===開発===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
npm run dev&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Start_next_js.png | 300px]]&lt;br /&gt;
&lt;br /&gt;
===本番ビルド＋実行===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
npm run build&lt;br /&gt;
npm start&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==App Router==&lt;br /&gt;
*React Routerとは異なる独自のルーターを標準で提供&lt;br /&gt;
*コンポーネントそのものはReactと変わらない&lt;br /&gt;
&lt;br /&gt;
===2種類のルーター===&lt;br /&gt;
&lt;br /&gt;
*Pages Router : 旧来から提供されている&lt;br /&gt;
*App Router : Next.js 13から導入された新しいルーター(推奨)&lt;br /&gt;
&lt;br /&gt;
====App Router====&lt;br /&gt;
*フォルダベースのルーター&lt;br /&gt;
*ルート定義不要、フォルダ階層に準じてリクエストパスとコンポーネント(.jsファイル)との対応関係が決まる&lt;br /&gt;
*page.jsはファイル名も固定でフォルダー構造だけでリクエストパスが決定される&lt;br /&gt;
&lt;br /&gt;
=====アプリ共通の外枠=====&lt;br /&gt;
*layout.js&lt;br /&gt;
*&amp;amp;lt;html&amp;amp;gt;、&amp;amp;lt;body&amp;amp;gt; 要素が存在し、個々のページを埋め込むため chilrenプロパティを引用していることが条件&lt;br /&gt;
&lt;br /&gt;
===ルートパラメータ===&lt;br /&gt;
*[名前] ： 単一パラメータ&lt;br /&gt;
*[...名前] : キャッチオールセグメント&lt;br /&gt;
*&amp;lt;nowiki&amp;gt;[[...名前]]&amp;lt;/nowiki&amp;gt; : 省略可能なキャッチオールセグメント&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ App Routerのルートパラメータ&lt;br /&gt;
|-&lt;br /&gt;
! フォルダ階層 !! 対応リクエスト !! パラメータ&lt;br /&gt;
|-&lt;br /&gt;
| /app/hoge/[id]/page.js || /hoge/001 || { id : '001' }&lt;br /&gt;
|-&lt;br /&gt;
| /app/foo/[...keys]/page.js || /foo/aaa/bbb || { keys: ['aaa', 'bbb'] }&lt;br /&gt;
|-&lt;br /&gt;
| /app/bar/&amp;lt;nowiki&amp;gt;[[...keys]]&amp;lt;/nowiki&amp;gt;/page.js || /bar || {}&lt;br /&gt;
|-&lt;br /&gt;
| 〃 || /bar/aaa/bbb || { keys: ['aaa', 'bbb'] }&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Tailwind CSS==&lt;br /&gt;
*https://tailwindcss.com/&lt;br /&gt;
*ユーティリティファーストをコンセプトに開発されたCSSフレームワーク&lt;br /&gt;
*ユーティリティを組み合わせてデザインを作るので独自のスタイルを作りやすく細かな調整もしやすいメリット&lt;br /&gt;
*標準のサイズ、カラーなどは用意されている&lt;br /&gt;
&lt;br /&gt;
[https://tailwindcsscheatsheet.com/ Cheat Sheet]&lt;br /&gt;
&lt;br /&gt;
*Tailwind　CSSによるスタイルを適用&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import &amp;quot;./globals.css&amp;quot;;&lt;br /&gt;
    :&lt;br /&gt;
&lt;br /&gt;
&amp;amp;lt;ul className=&amp;quot;fle bg-blue-600 mb-4 pl-2&amp;quot;&amp;amp;gt;...&amp;amp;lt;/ul&amp;amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Prisma==&lt;br /&gt;
*JavaScriptアプリからデータベース操作を取り持つO/Rマッパー&lt;br /&gt;
===インストール===&lt;br /&gt;
*成功すると以下のファイルが生成される&lt;br /&gt;
**.env : 環境変数ファイル、gitignore に追加する&lt;br /&gt;
** prisma/schema.prisma : Prismaのスキーマファイル&lt;br /&gt;
&lt;br /&gt;
sqliteでの構成例&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ npm install prisma --save-dev&lt;br /&gt;
 $ npx prisma init --datasource-provider sqlite&lt;br /&gt;
 warn You already have a .gitignore file. Don't forget to add `.env` in it to not commit any private information.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===データモデルの定義===&lt;br /&gt;
*prisma/schema.prisma に追記&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
model　reviews {&lt;br /&gt;
  id          String @id&lt;br /&gt;
  title       String&lt;br /&gt;
  author      String&lt;br /&gt;
  price       Int&lt;br /&gt;
  publlisher  String&lt;br /&gt;
  published   String&lt;br /&gt;
  image       String&lt;br /&gt;
  read        DateTime  @default(now())&lt;br /&gt;
  memo        String&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*DBに反映&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ npx prisma db push&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Prisma Studio(Webベース管理ツール)で確認&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ npx prisma studio&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Error: @prisma/client did not initialize yet. Please run &amp;quot;prisma generate&amp;quot; and try to import it again.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ nps prisma generate&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import { PrismaClient } from &amp;quot;@prisma/client&amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Prisma Clientの利用&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import { PrismaClient } from &amp;quot;@prisma/client&amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==サーバーアクション==&lt;br /&gt;
*Next.js内蔵の仕組み&lt;br /&gt;
*ページコンポーネント、イベントハンドラー、&amp;amp;lt;form&amp;amp;lt;要素のaction属性などからサーバーコードを呼び出す仕組み&lt;br /&gt;
*サーバーとのやりとりに際し、fetchなどの非同期通信コードの不要となり、例えばコンポーネントからデータベースを操作するにも直感的なコードを記述できる&lt;br /&gt;
*現時点ではα版&lt;br /&gt;
&lt;br /&gt;
===有効化===&lt;br /&gt;
&lt;br /&gt;
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]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
const nextConfig = {&lt;br /&gt;
    experimental: {&lt;br /&gt;
        serverActions: true&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=サーバーコンポーネント=&lt;br /&gt;
*https://qiita.com/kenogi/items/f216359576a4aa5a4b74#:~:text=Next.js%20%E3%81%AB%E3%81%8A&lt;br /&gt;
*https://qiita.com/keitaMax/items/b74ef76171224c2587c4#:~:text=React%20Serv&lt;br /&gt;
&lt;br /&gt;
*Next.jsの基本はサーバーコンポーネント&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=実装=&lt;br /&gt;
&lt;br /&gt;
==ルートレイアウト==&lt;br /&gt;
===アプリ内のリンクにはLinkコンポーネントを利用===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import Link from &amp;quot;next/link&amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
規定で以下のようなコンポーネントが用意されており、アプリ内リソースを効率的に利用できる&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ コンポーネント&lt;br /&gt;
|-&lt;br /&gt;
! コンポーネント !! 概要&lt;br /&gt;
|-&lt;br /&gt;
| &amp;amp;lt;Link&amp;amp;gt; || リンクを生成&lt;br /&gt;
|-&lt;br /&gt;
| &amp;amp;lt;Script&amp;amp;gt; || スクリプトのロード&lt;br /&gt;
|-&lt;br /&gt;
| &amp;amp;lt;Image&amp;amp;gt; || 画像を表示&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===メタデータ===&lt;br /&gt;
*メタデータを定義しておくことで、個々のページに適切なヘッダーなどを埋め込める&lt;br /&gt;
*複数箇所で宣言された場合、シャローマージされる&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
export const metadata: Metadata = {&lt;br /&gt;
  title: &amp;quot;Reading Recorder&amp;quot;,&lt;br /&gt;
  description: &amp;quot;自分が読んだ書籍の記録を残す&amp;quot;,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*generateMetadata関数を利用しデータベースなどから取得した結果を元に動的に生成も可能&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
export async function generateMetadata({ params, searchParams }) {&lt;br /&gt;
    :&lt;br /&gt;
    return {&lt;br /&gt;
        title : result.title,&lt;br /&gt;
            :&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=フォント=&lt;br /&gt;
*Googleフォント(無償フォントのディレクトリサービス)を有効化&lt;br /&gt;
*具体的なフォントはGoogleフォントから自由に選択できるが一般的にはバリアブルフォント推奨(下例ではInconsolata)&lt;br /&gt;
*フォントはファイルサイズが大きいので、subsetで利用する文字のみ取り出す&lt;br /&gt;
*fnc.className でフォントを適用できる&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import { Inconsolata } from 'next/font/google';&lt;br /&gt;
const fnt = Inconsolata({ subsets: ['latin'] });&lt;br /&gt;
&lt;br /&gt;
  :&lt;br /&gt;
&amp;amp;lt;body className={`${fnt.className}` }&amp;amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=MUI=&lt;br /&gt;
[[MUI]]&lt;br /&gt;
&lt;br /&gt;
=Tips=&lt;br /&gt;
&lt;br /&gt;
==リモートホストからの画像表示を許可する==&lt;br /&gt;
*next.config.mjs&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
const nextConfig = {&lt;br /&gt;
&lt;br /&gt;
    :&lt;br /&gt;
&lt;br /&gt;
    images: {&lt;br /&gt;
        remotePatterns: [&lt;br /&gt;
            {&lt;br /&gt;
                hostname: 'books.google.com'&lt;br /&gt;
            } &lt;br /&gt;
        ] &lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Piroto</name></author>
		
	</entry>
	<entry>
		<id>https://www.typea.info/tips_/index.php?title=Next.js&amp;diff=35339</id>
		<title>Next.js</title>
		<link rel="alternate" type="text/html" href="https://www.typea.info/tips_/index.php?title=Next.js&amp;diff=35339"/>
		<updated>2024-10-05T15:06:02Z</updated>

		<summary type="html">&lt;p&gt;Piroto: /* サーバーコンポーネント */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[React]] | [[MUI]] |&lt;br /&gt;
&lt;br /&gt;
{{amazon|4815619484}}&lt;br /&gt;
&lt;br /&gt;
=概要=&lt;br /&gt;
*Reactは、あくまでUI部分のみ&lt;br /&gt;
*本格的なアプリ開発には周辺領域を担うためのフレームワークが必要&lt;br /&gt;
*Reactベースのフレームワークとしてデファクトスタンダードと言える存在&lt;br /&gt;
*主なライブラリ&lt;br /&gt;
**ファイルシステムベースの設定レスルーター&lt;br /&gt;
**サーバーコンポーネント&lt;br /&gt;
**データ取得用fetchメソッド&lt;br /&gt;
**リソース組み込みの自動最適化&lt;br /&gt;
**CSSフレームワーク、Tailwind　CSSへの標準対応&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=導入=&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
newdelhi:Workspaces piroto$ npx create-next-app@latest&lt;br /&gt;
Need to install the following packages:&lt;br /&gt;
create-next-app@14.2.14&lt;br /&gt;
Ok to proceed? (y) y&lt;br /&gt;
&lt;br /&gt;
✔ What is your project named? … first-nextjs-app&lt;br /&gt;
✔ Would you like to use TypeScript? … No / Yes&lt;br /&gt;
✔ Would you like to use ESLint? … No / Yes&lt;br /&gt;
✔ Would you like to use Tailwind CSS? … No / Yes&lt;br /&gt;
✔ Would you like to use `src/` directory? … No / Yes&lt;br /&gt;
✔ Would you like to use App Router? (recommended) … No / Yes&lt;br /&gt;
✔ Would you like to customize the default import alias (@/*)? … No / Yes&lt;br /&gt;
Creating a new Next.js app in /Users/piroto/Workspaces/first-nextjs-app.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==実行==&lt;br /&gt;
===開発===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
npm run dev&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Start_next_js.png | 300px]]&lt;br /&gt;
&lt;br /&gt;
===本番ビルド＋実行===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
npm run build&lt;br /&gt;
npm start&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==App Router==&lt;br /&gt;
*React Routerとは異なる独自のルーターを標準で提供&lt;br /&gt;
*コンポーネントそのものはReactと変わらない&lt;br /&gt;
&lt;br /&gt;
===2種類のルーター===&lt;br /&gt;
&lt;br /&gt;
*Pages Router : 旧来から提供されている&lt;br /&gt;
*App Router : Next.js 13から導入された新しいルーター(推奨)&lt;br /&gt;
&lt;br /&gt;
====App Router====&lt;br /&gt;
*フォルダベースのルーター&lt;br /&gt;
*ルート定義不要、フォルダ階層に準じてリクエストパスとコンポーネント(.jsファイル)との対応関係が決まる&lt;br /&gt;
*page.jsはファイル名も固定でフォルダー構造だけでリクエストパスが決定される&lt;br /&gt;
&lt;br /&gt;
=====アプリ共通の外枠=====&lt;br /&gt;
*layout.js&lt;br /&gt;
*&amp;amp;lt;html&amp;amp;gt;、&amp;amp;lt;body&amp;amp;gt; 要素が存在し、個々のページを埋め込むため chilrenプロパティを引用していることが条件&lt;br /&gt;
&lt;br /&gt;
===ルートパラメータ===&lt;br /&gt;
*[名前] ： 単一パラメータ&lt;br /&gt;
*[...名前] : キャッチオールセグメント&lt;br /&gt;
*&amp;lt;nowiki&amp;gt;[[...名前]]&amp;lt;/nowiki&amp;gt; : 省略可能なキャッチオールセグメント&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ App Routerのルートパラメータ&lt;br /&gt;
|-&lt;br /&gt;
! フォルダ階層 !! 対応リクエスト !! パラメータ&lt;br /&gt;
|-&lt;br /&gt;
| /app/hoge/[id]/page.js || /hoge/001 || { id : '001' }&lt;br /&gt;
|-&lt;br /&gt;
| /app/foo/[...keys]/page.js || /foo/aaa/bbb || { keys: ['aaa', 'bbb'] }&lt;br /&gt;
|-&lt;br /&gt;
| /app/bar/&amp;lt;nowiki&amp;gt;[[...keys]]&amp;lt;/nowiki&amp;gt;/page.js || /bar || {}&lt;br /&gt;
|-&lt;br /&gt;
| 〃 || /bar/aaa/bbb || { keys: ['aaa', 'bbb'] }&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Tailwind CSS==&lt;br /&gt;
*https://tailwindcss.com/&lt;br /&gt;
*ユーティリティファーストをコンセプトに開発されたCSSフレームワーク&lt;br /&gt;
*ユーティリティを組み合わせてデザインを作るので独自のスタイルを作りやすく細かな調整もしやすいメリット&lt;br /&gt;
*標準のサイズ、カラーなどは用意されている&lt;br /&gt;
&lt;br /&gt;
[https://tailwindcsscheatsheet.com/ Cheat Sheet]&lt;br /&gt;
&lt;br /&gt;
*Tailwind　CSSによるスタイルを適用&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import &amp;quot;./globals.css&amp;quot;;&lt;br /&gt;
    :&lt;br /&gt;
&lt;br /&gt;
&amp;amp;lt;ul className=&amp;quot;fle bg-blue-600 mb-4 pl-2&amp;quot;&amp;amp;gt;...&amp;amp;lt;/ul&amp;amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Prisma==&lt;br /&gt;
*JavaScriptアプリからデータベース操作を取り持つO/Rマッパー&lt;br /&gt;
===インストール===&lt;br /&gt;
*成功すると以下のファイルが生成される&lt;br /&gt;
**.env : 環境変数ファイル、gitignore に追加する&lt;br /&gt;
** prisma/schema.prisma : Prismaのスキーマファイル&lt;br /&gt;
&lt;br /&gt;
sqliteでの構成例&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ npm install prisma --save-dev&lt;br /&gt;
 $ npx prisma init --datasource-provider sqlite&lt;br /&gt;
 warn You already have a .gitignore file. Don't forget to add `.env` in it to not commit any private information.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===データモデルの定義===&lt;br /&gt;
*prisma/schema.prisma に追記&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
model　reviews {&lt;br /&gt;
  id          String @id&lt;br /&gt;
  title       String&lt;br /&gt;
  author      String&lt;br /&gt;
  price       Int&lt;br /&gt;
  publlisher  String&lt;br /&gt;
  published   String&lt;br /&gt;
  image       String&lt;br /&gt;
  read        DateTime  @default(now())&lt;br /&gt;
  memo        String&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*DBに反映&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ npx prisma db push&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Prisma Studio(Webベース管理ツール)で確認&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ npx prisma studio&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Error: @prisma/client did not initialize yet. Please run &amp;quot;prisma generate&amp;quot; and try to import it again.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ nps prisma generate&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import { PrismaClient } from &amp;quot;@prisma/client&amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Prisma Clientの利用&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import { PrismaClient } from &amp;quot;@prisma/client&amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==サーバーアクション==&lt;br /&gt;
*Next.js内蔵の仕組み&lt;br /&gt;
*ページコンポーネント、イベントハンドラー、&amp;amp;lt;form&amp;amp;lt;要素のaction属性などからサーバーコードを呼び出す仕組み&lt;br /&gt;
*サーバーとのやりとりに際し、fetchなどの非同期通信コードの不要となり、例えばコンポーネントからデータベースを操作するにも直感的なコードを記述できる&lt;br /&gt;
*現時点ではα版&lt;br /&gt;
&lt;br /&gt;
===有効化===&lt;br /&gt;
&lt;br /&gt;
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]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
const nextConfig = {&lt;br /&gt;
    experimental: {&lt;br /&gt;
        serverActions: true&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=実装=&lt;br /&gt;
&lt;br /&gt;
==ルートレイアウト==&lt;br /&gt;
===アプリ内のリンクにはLinkコンポーネントを利用===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import Link from &amp;quot;next/link&amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
規定で以下のようなコンポーネントが用意されており、アプリ内リソースを効率的に利用できる&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ コンポーネント&lt;br /&gt;
|-&lt;br /&gt;
! コンポーネント !! 概要&lt;br /&gt;
|-&lt;br /&gt;
| &amp;amp;lt;Link&amp;amp;gt; || リンクを生成&lt;br /&gt;
|-&lt;br /&gt;
| &amp;amp;lt;Script&amp;amp;gt; || スクリプトのロード&lt;br /&gt;
|-&lt;br /&gt;
| &amp;amp;lt;Image&amp;amp;gt; || 画像を表示&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===メタデータ===&lt;br /&gt;
*メタデータを定義しておくことで、個々のページに適切なヘッダーなどを埋め込める&lt;br /&gt;
*複数箇所で宣言された場合、シャローマージされる&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
export const metadata: Metadata = {&lt;br /&gt;
  title: &amp;quot;Reading Recorder&amp;quot;,&lt;br /&gt;
  description: &amp;quot;自分が読んだ書籍の記録を残す&amp;quot;,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*generateMetadata関数を利用しデータベースなどから取得した結果を元に動的に生成も可能&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
export async function generateMetadata({ params, searchParams }) {&lt;br /&gt;
    :&lt;br /&gt;
    return {&lt;br /&gt;
        title : result.title,&lt;br /&gt;
            :&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=フォント=&lt;br /&gt;
*Googleフォント(無償フォントのディレクトリサービス)を有効化&lt;br /&gt;
*具体的なフォントはGoogleフォントから自由に選択できるが一般的にはバリアブルフォント推奨(下例ではInconsolata)&lt;br /&gt;
*フォントはファイルサイズが大きいので、subsetで利用する文字のみ取り出す&lt;br /&gt;
*fnc.className でフォントを適用できる&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import { Inconsolata } from 'next/font/google';&lt;br /&gt;
const fnt = Inconsolata({ subsets: ['latin'] });&lt;br /&gt;
&lt;br /&gt;
  :&lt;br /&gt;
&amp;amp;lt;body className={`${fnt.className}` }&amp;amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=MUI=&lt;br /&gt;
[[MUI]]&lt;br /&gt;
&lt;br /&gt;
=サーバーコンポーネント=&lt;br /&gt;
*https://qiita.com/kenogi/items/f216359576a4aa5a4b74#:~:text=Next.js%20%E3%81%AB%E3%81%8A&lt;br /&gt;
*https://qiita.com/keitaMax/items/b74ef76171224c2587c4#:~:text=React%20Serv&lt;br /&gt;
&lt;br /&gt;
*Next.jsの基本はサーバーコンポーネント&lt;br /&gt;
&lt;br /&gt;
=Tips=&lt;br /&gt;
&lt;br /&gt;
==リモートホストからの画像表示を許可する==&lt;br /&gt;
*next.config.mjs&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
const nextConfig = {&lt;br /&gt;
&lt;br /&gt;
    :&lt;br /&gt;
&lt;br /&gt;
    images: {&lt;br /&gt;
        remotePatterns: [&lt;br /&gt;
            {&lt;br /&gt;
                hostname: 'books.google.com'&lt;br /&gt;
            } &lt;br /&gt;
        ] &lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Piroto</name></author>
		
	</entry>
	<entry>
		<id>https://www.typea.info/tips_/index.php?title=Next.js&amp;diff=35338</id>
		<title>Next.js</title>
		<link rel="alternate" type="text/html" href="https://www.typea.info/tips_/index.php?title=Next.js&amp;diff=35338"/>
		<updated>2024-10-05T15:04:33Z</updated>

		<summary type="html">&lt;p&gt;Piroto: /* サーバーコンポーネント */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[React]] | [[MUI]] |&lt;br /&gt;
&lt;br /&gt;
{{amazon|4815619484}}&lt;br /&gt;
&lt;br /&gt;
=概要=&lt;br /&gt;
*Reactは、あくまでUI部分のみ&lt;br /&gt;
*本格的なアプリ開発には周辺領域を担うためのフレームワークが必要&lt;br /&gt;
*Reactベースのフレームワークとしてデファクトスタンダードと言える存在&lt;br /&gt;
*主なライブラリ&lt;br /&gt;
**ファイルシステムベースの設定レスルーター&lt;br /&gt;
**サーバーコンポーネント&lt;br /&gt;
**データ取得用fetchメソッド&lt;br /&gt;
**リソース組み込みの自動最適化&lt;br /&gt;
**CSSフレームワーク、Tailwind　CSSへの標準対応&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=導入=&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
newdelhi:Workspaces piroto$ npx create-next-app@latest&lt;br /&gt;
Need to install the following packages:&lt;br /&gt;
create-next-app@14.2.14&lt;br /&gt;
Ok to proceed? (y) y&lt;br /&gt;
&lt;br /&gt;
✔ What is your project named? … first-nextjs-app&lt;br /&gt;
✔ Would you like to use TypeScript? … No / Yes&lt;br /&gt;
✔ Would you like to use ESLint? … No / Yes&lt;br /&gt;
✔ Would you like to use Tailwind CSS? … No / Yes&lt;br /&gt;
✔ Would you like to use `src/` directory? … No / Yes&lt;br /&gt;
✔ Would you like to use App Router? (recommended) … No / Yes&lt;br /&gt;
✔ Would you like to customize the default import alias (@/*)? … No / Yes&lt;br /&gt;
Creating a new Next.js app in /Users/piroto/Workspaces/first-nextjs-app.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==実行==&lt;br /&gt;
===開発===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
npm run dev&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Start_next_js.png | 300px]]&lt;br /&gt;
&lt;br /&gt;
===本番ビルド＋実行===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
npm run build&lt;br /&gt;
npm start&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==App Router==&lt;br /&gt;
*React Routerとは異なる独自のルーターを標準で提供&lt;br /&gt;
*コンポーネントそのものはReactと変わらない&lt;br /&gt;
&lt;br /&gt;
===2種類のルーター===&lt;br /&gt;
&lt;br /&gt;
*Pages Router : 旧来から提供されている&lt;br /&gt;
*App Router : Next.js 13から導入された新しいルーター(推奨)&lt;br /&gt;
&lt;br /&gt;
====App Router====&lt;br /&gt;
*フォルダベースのルーター&lt;br /&gt;
*ルート定義不要、フォルダ階層に準じてリクエストパスとコンポーネント(.jsファイル)との対応関係が決まる&lt;br /&gt;
*page.jsはファイル名も固定でフォルダー構造だけでリクエストパスが決定される&lt;br /&gt;
&lt;br /&gt;
=====アプリ共通の外枠=====&lt;br /&gt;
*layout.js&lt;br /&gt;
*&amp;amp;lt;html&amp;amp;gt;、&amp;amp;lt;body&amp;amp;gt; 要素が存在し、個々のページを埋め込むため chilrenプロパティを引用していることが条件&lt;br /&gt;
&lt;br /&gt;
===ルートパラメータ===&lt;br /&gt;
*[名前] ： 単一パラメータ&lt;br /&gt;
*[...名前] : キャッチオールセグメント&lt;br /&gt;
*&amp;lt;nowiki&amp;gt;[[...名前]]&amp;lt;/nowiki&amp;gt; : 省略可能なキャッチオールセグメント&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ App Routerのルートパラメータ&lt;br /&gt;
|-&lt;br /&gt;
! フォルダ階層 !! 対応リクエスト !! パラメータ&lt;br /&gt;
|-&lt;br /&gt;
| /app/hoge/[id]/page.js || /hoge/001 || { id : '001' }&lt;br /&gt;
|-&lt;br /&gt;
| /app/foo/[...keys]/page.js || /foo/aaa/bbb || { keys: ['aaa', 'bbb'] }&lt;br /&gt;
|-&lt;br /&gt;
| /app/bar/&amp;lt;nowiki&amp;gt;[[...keys]]&amp;lt;/nowiki&amp;gt;/page.js || /bar || {}&lt;br /&gt;
|-&lt;br /&gt;
| 〃 || /bar/aaa/bbb || { keys: ['aaa', 'bbb'] }&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Tailwind CSS==&lt;br /&gt;
*https://tailwindcss.com/&lt;br /&gt;
*ユーティリティファーストをコンセプトに開発されたCSSフレームワーク&lt;br /&gt;
*ユーティリティを組み合わせてデザインを作るので独自のスタイルを作りやすく細かな調整もしやすいメリット&lt;br /&gt;
*標準のサイズ、カラーなどは用意されている&lt;br /&gt;
&lt;br /&gt;
[https://tailwindcsscheatsheet.com/ Cheat Sheet]&lt;br /&gt;
&lt;br /&gt;
*Tailwind　CSSによるスタイルを適用&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import &amp;quot;./globals.css&amp;quot;;&lt;br /&gt;
    :&lt;br /&gt;
&lt;br /&gt;
&amp;amp;lt;ul className=&amp;quot;fle bg-blue-600 mb-4 pl-2&amp;quot;&amp;amp;gt;...&amp;amp;lt;/ul&amp;amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Prisma==&lt;br /&gt;
*JavaScriptアプリからデータベース操作を取り持つO/Rマッパー&lt;br /&gt;
===インストール===&lt;br /&gt;
*成功すると以下のファイルが生成される&lt;br /&gt;
**.env : 環境変数ファイル、gitignore に追加する&lt;br /&gt;
** prisma/schema.prisma : Prismaのスキーマファイル&lt;br /&gt;
&lt;br /&gt;
sqliteでの構成例&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ npm install prisma --save-dev&lt;br /&gt;
 $ npx prisma init --datasource-provider sqlite&lt;br /&gt;
 warn You already have a .gitignore file. Don't forget to add `.env` in it to not commit any private information.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===データモデルの定義===&lt;br /&gt;
*prisma/schema.prisma に追記&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
model　reviews {&lt;br /&gt;
  id          String @id&lt;br /&gt;
  title       String&lt;br /&gt;
  author      String&lt;br /&gt;
  price       Int&lt;br /&gt;
  publlisher  String&lt;br /&gt;
  published   String&lt;br /&gt;
  image       String&lt;br /&gt;
  read        DateTime  @default(now())&lt;br /&gt;
  memo        String&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*DBに反映&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ npx prisma db push&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Prisma Studio(Webベース管理ツール)で確認&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ npx prisma studio&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Error: @prisma/client did not initialize yet. Please run &amp;quot;prisma generate&amp;quot; and try to import it again.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ nps prisma generate&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import { PrismaClient } from &amp;quot;@prisma/client&amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Prisma Clientの利用&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import { PrismaClient } from &amp;quot;@prisma/client&amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==サーバーアクション==&lt;br /&gt;
*Next.js内蔵の仕組み&lt;br /&gt;
*ページコンポーネント、イベントハンドラー、&amp;amp;lt;form&amp;amp;lt;要素のaction属性などからサーバーコードを呼び出す仕組み&lt;br /&gt;
*サーバーとのやりとりに際し、fetchなどの非同期通信コードの不要となり、例えばコンポーネントからデータベースを操作するにも直感的なコードを記述できる&lt;br /&gt;
*現時点ではα版&lt;br /&gt;
&lt;br /&gt;
===有効化===&lt;br /&gt;
&lt;br /&gt;
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]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
const nextConfig = {&lt;br /&gt;
    experimental: {&lt;br /&gt;
        serverActions: true&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=実装=&lt;br /&gt;
&lt;br /&gt;
==ルートレイアウト==&lt;br /&gt;
===アプリ内のリンクにはLinkコンポーネントを利用===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import Link from &amp;quot;next/link&amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
規定で以下のようなコンポーネントが用意されており、アプリ内リソースを効率的に利用できる&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ コンポーネント&lt;br /&gt;
|-&lt;br /&gt;
! コンポーネント !! 概要&lt;br /&gt;
|-&lt;br /&gt;
| &amp;amp;lt;Link&amp;amp;gt; || リンクを生成&lt;br /&gt;
|-&lt;br /&gt;
| &amp;amp;lt;Script&amp;amp;gt; || スクリプトのロード&lt;br /&gt;
|-&lt;br /&gt;
| &amp;amp;lt;Image&amp;amp;gt; || 画像を表示&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===メタデータ===&lt;br /&gt;
*メタデータを定義しておくことで、個々のページに適切なヘッダーなどを埋め込める&lt;br /&gt;
*複数箇所で宣言された場合、シャローマージされる&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
export const metadata: Metadata = {&lt;br /&gt;
  title: &amp;quot;Reading Recorder&amp;quot;,&lt;br /&gt;
  description: &amp;quot;自分が読んだ書籍の記録を残す&amp;quot;,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*generateMetadata関数を利用しデータベースなどから取得した結果を元に動的に生成も可能&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
export async function generateMetadata({ params, searchParams }) {&lt;br /&gt;
    :&lt;br /&gt;
    return {&lt;br /&gt;
        title : result.title,&lt;br /&gt;
            :&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=フォント=&lt;br /&gt;
*Googleフォント(無償フォントのディレクトリサービス)を有効化&lt;br /&gt;
*具体的なフォントはGoogleフォントから自由に選択できるが一般的にはバリアブルフォント推奨(下例ではInconsolata)&lt;br /&gt;
*フォントはファイルサイズが大きいので、subsetで利用する文字のみ取り出す&lt;br /&gt;
*fnc.className でフォントを適用できる&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import { Inconsolata } from 'next/font/google';&lt;br /&gt;
const fnt = Inconsolata({ subsets: ['latin'] });&lt;br /&gt;
&lt;br /&gt;
  :&lt;br /&gt;
&amp;amp;lt;body className={`${fnt.className}` }&amp;amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=MUI=&lt;br /&gt;
[[MUI]]&lt;br /&gt;
&lt;br /&gt;
=サーバーコンポーネント=&lt;br /&gt;
*https://qiita.com/kenogi/items/f216359576a4aa5a4b74#:~:text=Next.js%20%E3%81%AB%E3%81%8A&lt;br /&gt;
*Next.jsの基本はサーバーコンポーネント&lt;br /&gt;
&lt;br /&gt;
=Tips=&lt;br /&gt;
&lt;br /&gt;
==リモートホストからの画像表示を許可する==&lt;br /&gt;
*next.config.mjs&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
const nextConfig = {&lt;br /&gt;
&lt;br /&gt;
    :&lt;br /&gt;
&lt;br /&gt;
    images: {&lt;br /&gt;
        remotePatterns: [&lt;br /&gt;
            {&lt;br /&gt;
                hostname: 'books.google.com'&lt;br /&gt;
            } &lt;br /&gt;
        ] &lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Piroto</name></author>
		
	</entry>
	<entry>
		<id>https://www.typea.info/tips_/index.php?title=Next.js&amp;diff=35337</id>
		<title>Next.js</title>
		<link rel="alternate" type="text/html" href="https://www.typea.info/tips_/index.php?title=Next.js&amp;diff=35337"/>
		<updated>2024-10-05T15:03:32Z</updated>

		<summary type="html">&lt;p&gt;Piroto: /* MUI */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[React]] | [[MUI]] |&lt;br /&gt;
&lt;br /&gt;
{{amazon|4815619484}}&lt;br /&gt;
&lt;br /&gt;
=概要=&lt;br /&gt;
*Reactは、あくまでUI部分のみ&lt;br /&gt;
*本格的なアプリ開発には周辺領域を担うためのフレームワークが必要&lt;br /&gt;
*Reactベースのフレームワークとしてデファクトスタンダードと言える存在&lt;br /&gt;
*主なライブラリ&lt;br /&gt;
**ファイルシステムベースの設定レスルーター&lt;br /&gt;
**サーバーコンポーネント&lt;br /&gt;
**データ取得用fetchメソッド&lt;br /&gt;
**リソース組み込みの自動最適化&lt;br /&gt;
**CSSフレームワーク、Tailwind　CSSへの標準対応&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=導入=&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
newdelhi:Workspaces piroto$ npx create-next-app@latest&lt;br /&gt;
Need to install the following packages:&lt;br /&gt;
create-next-app@14.2.14&lt;br /&gt;
Ok to proceed? (y) y&lt;br /&gt;
&lt;br /&gt;
✔ What is your project named? … first-nextjs-app&lt;br /&gt;
✔ Would you like to use TypeScript? … No / Yes&lt;br /&gt;
✔ Would you like to use ESLint? … No / Yes&lt;br /&gt;
✔ Would you like to use Tailwind CSS? … No / Yes&lt;br /&gt;
✔ Would you like to use `src/` directory? … No / Yes&lt;br /&gt;
✔ Would you like to use App Router? (recommended) … No / Yes&lt;br /&gt;
✔ Would you like to customize the default import alias (@/*)? … No / Yes&lt;br /&gt;
Creating a new Next.js app in /Users/piroto/Workspaces/first-nextjs-app.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==実行==&lt;br /&gt;
===開発===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
npm run dev&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Start_next_js.png | 300px]]&lt;br /&gt;
&lt;br /&gt;
===本番ビルド＋実行===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
npm run build&lt;br /&gt;
npm start&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==App Router==&lt;br /&gt;
*React Routerとは異なる独自のルーターを標準で提供&lt;br /&gt;
*コンポーネントそのものはReactと変わらない&lt;br /&gt;
&lt;br /&gt;
===2種類のルーター===&lt;br /&gt;
&lt;br /&gt;
*Pages Router : 旧来から提供されている&lt;br /&gt;
*App Router : Next.js 13から導入された新しいルーター(推奨)&lt;br /&gt;
&lt;br /&gt;
====App Router====&lt;br /&gt;
*フォルダベースのルーター&lt;br /&gt;
*ルート定義不要、フォルダ階層に準じてリクエストパスとコンポーネント(.jsファイル)との対応関係が決まる&lt;br /&gt;
*page.jsはファイル名も固定でフォルダー構造だけでリクエストパスが決定される&lt;br /&gt;
&lt;br /&gt;
=====アプリ共通の外枠=====&lt;br /&gt;
*layout.js&lt;br /&gt;
*&amp;amp;lt;html&amp;amp;gt;、&amp;amp;lt;body&amp;amp;gt; 要素が存在し、個々のページを埋め込むため chilrenプロパティを引用していることが条件&lt;br /&gt;
&lt;br /&gt;
===ルートパラメータ===&lt;br /&gt;
*[名前] ： 単一パラメータ&lt;br /&gt;
*[...名前] : キャッチオールセグメント&lt;br /&gt;
*&amp;lt;nowiki&amp;gt;[[...名前]]&amp;lt;/nowiki&amp;gt; : 省略可能なキャッチオールセグメント&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ App Routerのルートパラメータ&lt;br /&gt;
|-&lt;br /&gt;
! フォルダ階層 !! 対応リクエスト !! パラメータ&lt;br /&gt;
|-&lt;br /&gt;
| /app/hoge/[id]/page.js || /hoge/001 || { id : '001' }&lt;br /&gt;
|-&lt;br /&gt;
| /app/foo/[...keys]/page.js || /foo/aaa/bbb || { keys: ['aaa', 'bbb'] }&lt;br /&gt;
|-&lt;br /&gt;
| /app/bar/&amp;lt;nowiki&amp;gt;[[...keys]]&amp;lt;/nowiki&amp;gt;/page.js || /bar || {}&lt;br /&gt;
|-&lt;br /&gt;
| 〃 || /bar/aaa/bbb || { keys: ['aaa', 'bbb'] }&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Tailwind CSS==&lt;br /&gt;
*https://tailwindcss.com/&lt;br /&gt;
*ユーティリティファーストをコンセプトに開発されたCSSフレームワーク&lt;br /&gt;
*ユーティリティを組み合わせてデザインを作るので独自のスタイルを作りやすく細かな調整もしやすいメリット&lt;br /&gt;
*標準のサイズ、カラーなどは用意されている&lt;br /&gt;
&lt;br /&gt;
[https://tailwindcsscheatsheet.com/ Cheat Sheet]&lt;br /&gt;
&lt;br /&gt;
*Tailwind　CSSによるスタイルを適用&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import &amp;quot;./globals.css&amp;quot;;&lt;br /&gt;
    :&lt;br /&gt;
&lt;br /&gt;
&amp;amp;lt;ul className=&amp;quot;fle bg-blue-600 mb-4 pl-2&amp;quot;&amp;amp;gt;...&amp;amp;lt;/ul&amp;amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Prisma==&lt;br /&gt;
*JavaScriptアプリからデータベース操作を取り持つO/Rマッパー&lt;br /&gt;
===インストール===&lt;br /&gt;
*成功すると以下のファイルが生成される&lt;br /&gt;
**.env : 環境変数ファイル、gitignore に追加する&lt;br /&gt;
** prisma/schema.prisma : Prismaのスキーマファイル&lt;br /&gt;
&lt;br /&gt;
sqliteでの構成例&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ npm install prisma --save-dev&lt;br /&gt;
 $ npx prisma init --datasource-provider sqlite&lt;br /&gt;
 warn You already have a .gitignore file. Don't forget to add `.env` in it to not commit any private information.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===データモデルの定義===&lt;br /&gt;
*prisma/schema.prisma に追記&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
model　reviews {&lt;br /&gt;
  id          String @id&lt;br /&gt;
  title       String&lt;br /&gt;
  author      String&lt;br /&gt;
  price       Int&lt;br /&gt;
  publlisher  String&lt;br /&gt;
  published   String&lt;br /&gt;
  image       String&lt;br /&gt;
  read        DateTime  @default(now())&lt;br /&gt;
  memo        String&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*DBに反映&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ npx prisma db push&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Prisma Studio(Webベース管理ツール)で確認&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ npx prisma studio&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Error: @prisma/client did not initialize yet. Please run &amp;quot;prisma generate&amp;quot; and try to import it again.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ nps prisma generate&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import { PrismaClient } from &amp;quot;@prisma/client&amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Prisma Clientの利用&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import { PrismaClient } from &amp;quot;@prisma/client&amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==サーバーアクション==&lt;br /&gt;
*Next.js内蔵の仕組み&lt;br /&gt;
*ページコンポーネント、イベントハンドラー、&amp;amp;lt;form&amp;amp;lt;要素のaction属性などからサーバーコードを呼び出す仕組み&lt;br /&gt;
*サーバーとのやりとりに際し、fetchなどの非同期通信コードの不要となり、例えばコンポーネントからデータベースを操作するにも直感的なコードを記述できる&lt;br /&gt;
*現時点ではα版&lt;br /&gt;
&lt;br /&gt;
===有効化===&lt;br /&gt;
&lt;br /&gt;
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]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
const nextConfig = {&lt;br /&gt;
    experimental: {&lt;br /&gt;
        serverActions: true&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=実装=&lt;br /&gt;
&lt;br /&gt;
==ルートレイアウト==&lt;br /&gt;
===アプリ内のリンクにはLinkコンポーネントを利用===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import Link from &amp;quot;next/link&amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
規定で以下のようなコンポーネントが用意されており、アプリ内リソースを効率的に利用できる&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ コンポーネント&lt;br /&gt;
|-&lt;br /&gt;
! コンポーネント !! 概要&lt;br /&gt;
|-&lt;br /&gt;
| &amp;amp;lt;Link&amp;amp;gt; || リンクを生成&lt;br /&gt;
|-&lt;br /&gt;
| &amp;amp;lt;Script&amp;amp;gt; || スクリプトのロード&lt;br /&gt;
|-&lt;br /&gt;
| &amp;amp;lt;Image&amp;amp;gt; || 画像を表示&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===メタデータ===&lt;br /&gt;
*メタデータを定義しておくことで、個々のページに適切なヘッダーなどを埋め込める&lt;br /&gt;
*複数箇所で宣言された場合、シャローマージされる&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
export const metadata: Metadata = {&lt;br /&gt;
  title: &amp;quot;Reading Recorder&amp;quot;,&lt;br /&gt;
  description: &amp;quot;自分が読んだ書籍の記録を残す&amp;quot;,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*generateMetadata関数を利用しデータベースなどから取得した結果を元に動的に生成も可能&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
export async function generateMetadata({ params, searchParams }) {&lt;br /&gt;
    :&lt;br /&gt;
    return {&lt;br /&gt;
        title : result.title,&lt;br /&gt;
            :&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=フォント=&lt;br /&gt;
*Googleフォント(無償フォントのディレクトリサービス)を有効化&lt;br /&gt;
*具体的なフォントはGoogleフォントから自由に選択できるが一般的にはバリアブルフォント推奨(下例ではInconsolata)&lt;br /&gt;
*フォントはファイルサイズが大きいので、subsetで利用する文字のみ取り出す&lt;br /&gt;
*fnc.className でフォントを適用できる&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import { Inconsolata } from 'next/font/google';&lt;br /&gt;
const fnt = Inconsolata({ subsets: ['latin'] });&lt;br /&gt;
&lt;br /&gt;
  :&lt;br /&gt;
&amp;amp;lt;body className={`${fnt.className}` }&amp;amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=MUI=&lt;br /&gt;
[[MUI]]&lt;br /&gt;
&lt;br /&gt;
=サーバーコンポーネント=&lt;br /&gt;
*Next.jsの基本はサーバーコンポーネント&lt;br /&gt;
&lt;br /&gt;
=Tips=&lt;br /&gt;
&lt;br /&gt;
==リモートホストからの画像表示を許可する==&lt;br /&gt;
*next.config.mjs&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
const nextConfig = {&lt;br /&gt;
&lt;br /&gt;
    :&lt;br /&gt;
&lt;br /&gt;
    images: {&lt;br /&gt;
        remotePatterns: [&lt;br /&gt;
            {&lt;br /&gt;
                hostname: 'books.google.com'&lt;br /&gt;
            } &lt;br /&gt;
        ] &lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Piroto</name></author>
		
	</entry>
	<entry>
		<id>https://www.typea.info/tips_/index.php?title=Next.js&amp;diff=35336</id>
		<title>Next.js</title>
		<link rel="alternate" type="text/html" href="https://www.typea.info/tips_/index.php?title=Next.js&amp;diff=35336"/>
		<updated>2024-10-05T15:00:43Z</updated>

		<summary type="html">&lt;p&gt;Piroto: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[React]] | [[MUI]] |&lt;br /&gt;
&lt;br /&gt;
{{amazon|4815619484}}&lt;br /&gt;
&lt;br /&gt;
=概要=&lt;br /&gt;
*Reactは、あくまでUI部分のみ&lt;br /&gt;
*本格的なアプリ開発には周辺領域を担うためのフレームワークが必要&lt;br /&gt;
*Reactベースのフレームワークとしてデファクトスタンダードと言える存在&lt;br /&gt;
*主なライブラリ&lt;br /&gt;
**ファイルシステムベースの設定レスルーター&lt;br /&gt;
**サーバーコンポーネント&lt;br /&gt;
**データ取得用fetchメソッド&lt;br /&gt;
**リソース組み込みの自動最適化&lt;br /&gt;
**CSSフレームワーク、Tailwind　CSSへの標準対応&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=導入=&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
newdelhi:Workspaces piroto$ npx create-next-app@latest&lt;br /&gt;
Need to install the following packages:&lt;br /&gt;
create-next-app@14.2.14&lt;br /&gt;
Ok to proceed? (y) y&lt;br /&gt;
&lt;br /&gt;
✔ What is your project named? … first-nextjs-app&lt;br /&gt;
✔ Would you like to use TypeScript? … No / Yes&lt;br /&gt;
✔ Would you like to use ESLint? … No / Yes&lt;br /&gt;
✔ Would you like to use Tailwind CSS? … No / Yes&lt;br /&gt;
✔ Would you like to use `src/` directory? … No / Yes&lt;br /&gt;
✔ Would you like to use App Router? (recommended) … No / Yes&lt;br /&gt;
✔ Would you like to customize the default import alias (@/*)? … No / Yes&lt;br /&gt;
Creating a new Next.js app in /Users/piroto/Workspaces/first-nextjs-app.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==実行==&lt;br /&gt;
===開発===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
npm run dev&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Start_next_js.png | 300px]]&lt;br /&gt;
&lt;br /&gt;
===本番ビルド＋実行===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
npm run build&lt;br /&gt;
npm start&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==App Router==&lt;br /&gt;
*React Routerとは異なる独自のルーターを標準で提供&lt;br /&gt;
*コンポーネントそのものはReactと変わらない&lt;br /&gt;
&lt;br /&gt;
===2種類のルーター===&lt;br /&gt;
&lt;br /&gt;
*Pages Router : 旧来から提供されている&lt;br /&gt;
*App Router : Next.js 13から導入された新しいルーター(推奨)&lt;br /&gt;
&lt;br /&gt;
====App Router====&lt;br /&gt;
*フォルダベースのルーター&lt;br /&gt;
*ルート定義不要、フォルダ階層に準じてリクエストパスとコンポーネント(.jsファイル)との対応関係が決まる&lt;br /&gt;
*page.jsはファイル名も固定でフォルダー構造だけでリクエストパスが決定される&lt;br /&gt;
&lt;br /&gt;
=====アプリ共通の外枠=====&lt;br /&gt;
*layout.js&lt;br /&gt;
*&amp;amp;lt;html&amp;amp;gt;、&amp;amp;lt;body&amp;amp;gt; 要素が存在し、個々のページを埋め込むため chilrenプロパティを引用していることが条件&lt;br /&gt;
&lt;br /&gt;
===ルートパラメータ===&lt;br /&gt;
*[名前] ： 単一パラメータ&lt;br /&gt;
*[...名前] : キャッチオールセグメント&lt;br /&gt;
*&amp;lt;nowiki&amp;gt;[[...名前]]&amp;lt;/nowiki&amp;gt; : 省略可能なキャッチオールセグメント&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ App Routerのルートパラメータ&lt;br /&gt;
|-&lt;br /&gt;
! フォルダ階層 !! 対応リクエスト !! パラメータ&lt;br /&gt;
|-&lt;br /&gt;
| /app/hoge/[id]/page.js || /hoge/001 || { id : '001' }&lt;br /&gt;
|-&lt;br /&gt;
| /app/foo/[...keys]/page.js || /foo/aaa/bbb || { keys: ['aaa', 'bbb'] }&lt;br /&gt;
|-&lt;br /&gt;
| /app/bar/&amp;lt;nowiki&amp;gt;[[...keys]]&amp;lt;/nowiki&amp;gt;/page.js || /bar || {}&lt;br /&gt;
|-&lt;br /&gt;
| 〃 || /bar/aaa/bbb || { keys: ['aaa', 'bbb'] }&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Tailwind CSS==&lt;br /&gt;
*https://tailwindcss.com/&lt;br /&gt;
*ユーティリティファーストをコンセプトに開発されたCSSフレームワーク&lt;br /&gt;
*ユーティリティを組み合わせてデザインを作るので独自のスタイルを作りやすく細かな調整もしやすいメリット&lt;br /&gt;
*標準のサイズ、カラーなどは用意されている&lt;br /&gt;
&lt;br /&gt;
[https://tailwindcsscheatsheet.com/ Cheat Sheet]&lt;br /&gt;
&lt;br /&gt;
*Tailwind　CSSによるスタイルを適用&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import &amp;quot;./globals.css&amp;quot;;&lt;br /&gt;
    :&lt;br /&gt;
&lt;br /&gt;
&amp;amp;lt;ul className=&amp;quot;fle bg-blue-600 mb-4 pl-2&amp;quot;&amp;amp;gt;...&amp;amp;lt;/ul&amp;amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Prisma==&lt;br /&gt;
*JavaScriptアプリからデータベース操作を取り持つO/Rマッパー&lt;br /&gt;
===インストール===&lt;br /&gt;
*成功すると以下のファイルが生成される&lt;br /&gt;
**.env : 環境変数ファイル、gitignore に追加する&lt;br /&gt;
** prisma/schema.prisma : Prismaのスキーマファイル&lt;br /&gt;
&lt;br /&gt;
sqliteでの構成例&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ npm install prisma --save-dev&lt;br /&gt;
 $ npx prisma init --datasource-provider sqlite&lt;br /&gt;
 warn You already have a .gitignore file. Don't forget to add `.env` in it to not commit any private information.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===データモデルの定義===&lt;br /&gt;
*prisma/schema.prisma に追記&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
model　reviews {&lt;br /&gt;
  id          String @id&lt;br /&gt;
  title       String&lt;br /&gt;
  author      String&lt;br /&gt;
  price       Int&lt;br /&gt;
  publlisher  String&lt;br /&gt;
  published   String&lt;br /&gt;
  image       String&lt;br /&gt;
  read        DateTime  @default(now())&lt;br /&gt;
  memo        String&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*DBに反映&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ npx prisma db push&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Prisma Studio(Webベース管理ツール)で確認&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ npx prisma studio&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Error: @prisma/client did not initialize yet. Please run &amp;quot;prisma generate&amp;quot; and try to import it again.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ nps prisma generate&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import { PrismaClient } from &amp;quot;@prisma/client&amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Prisma Clientの利用&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import { PrismaClient } from &amp;quot;@prisma/client&amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==サーバーアクション==&lt;br /&gt;
*Next.js内蔵の仕組み&lt;br /&gt;
*ページコンポーネント、イベントハンドラー、&amp;amp;lt;form&amp;amp;lt;要素のaction属性などからサーバーコードを呼び出す仕組み&lt;br /&gt;
*サーバーとのやりとりに際し、fetchなどの非同期通信コードの不要となり、例えばコンポーネントからデータベースを操作するにも直感的なコードを記述できる&lt;br /&gt;
*現時点ではα版&lt;br /&gt;
&lt;br /&gt;
===有効化===&lt;br /&gt;
&lt;br /&gt;
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]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
const nextConfig = {&lt;br /&gt;
    experimental: {&lt;br /&gt;
        serverActions: true&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=実装=&lt;br /&gt;
&lt;br /&gt;
==ルートレイアウト==&lt;br /&gt;
===アプリ内のリンクにはLinkコンポーネントを利用===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import Link from &amp;quot;next/link&amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
規定で以下のようなコンポーネントが用意されており、アプリ内リソースを効率的に利用できる&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ コンポーネント&lt;br /&gt;
|-&lt;br /&gt;
! コンポーネント !! 概要&lt;br /&gt;
|-&lt;br /&gt;
| &amp;amp;lt;Link&amp;amp;gt; || リンクを生成&lt;br /&gt;
|-&lt;br /&gt;
| &amp;amp;lt;Script&amp;amp;gt; || スクリプトのロード&lt;br /&gt;
|-&lt;br /&gt;
| &amp;amp;lt;Image&amp;amp;gt; || 画像を表示&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===メタデータ===&lt;br /&gt;
*メタデータを定義しておくことで、個々のページに適切なヘッダーなどを埋め込める&lt;br /&gt;
*複数箇所で宣言された場合、シャローマージされる&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
export const metadata: Metadata = {&lt;br /&gt;
  title: &amp;quot;Reading Recorder&amp;quot;,&lt;br /&gt;
  description: &amp;quot;自分が読んだ書籍の記録を残す&amp;quot;,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*generateMetadata関数を利用しデータベースなどから取得した結果を元に動的に生成も可能&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
export async function generateMetadata({ params, searchParams }) {&lt;br /&gt;
    :&lt;br /&gt;
    return {&lt;br /&gt;
        title : result.title,&lt;br /&gt;
            :&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=フォント=&lt;br /&gt;
*Googleフォント(無償フォントのディレクトリサービス)を有効化&lt;br /&gt;
*具体的なフォントはGoogleフォントから自由に選択できるが一般的にはバリアブルフォント推奨(下例ではInconsolata)&lt;br /&gt;
*フォントはファイルサイズが大きいので、subsetで利用する文字のみ取り出す&lt;br /&gt;
*fnc.className でフォントを適用できる&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import { Inconsolata } from 'next/font/google';&lt;br /&gt;
const fnt = Inconsolata({ subsets: ['latin'] });&lt;br /&gt;
&lt;br /&gt;
  :&lt;br /&gt;
&amp;amp;lt;body className={`${fnt.className}` }&amp;amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=MUI=&lt;br /&gt;
[[MUI]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Tips=&lt;br /&gt;
&lt;br /&gt;
==リモートホストからの画像表示を許可する==&lt;br /&gt;
*next.config.mjs&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
const nextConfig = {&lt;br /&gt;
&lt;br /&gt;
    :&lt;br /&gt;
&lt;br /&gt;
    images: {&lt;br /&gt;
        remotePatterns: [&lt;br /&gt;
            {&lt;br /&gt;
                hostname: 'books.google.com'&lt;br /&gt;
            } &lt;br /&gt;
        ] &lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Piroto</name></author>
		
	</entry>
	<entry>
		<id>https://www.typea.info/tips_/index.php?title=Next.js&amp;diff=35335</id>
		<title>Next.js</title>
		<link rel="alternate" type="text/html" href="https://www.typea.info/tips_/index.php?title=Next.js&amp;diff=35335"/>
		<updated>2024-10-05T14:57:15Z</updated>

		<summary type="html">&lt;p&gt;Piroto: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[React]] | [[MUI]] |&lt;br /&gt;
&lt;br /&gt;
{{amazon|4815619484}}&lt;br /&gt;
&lt;br /&gt;
=概要=&lt;br /&gt;
*Reactは、あくまでUI部分のみ&lt;br /&gt;
*本格的なアプリ開発には周辺領域を担うためのフレームワークが必要&lt;br /&gt;
*Reactベースのフレームワークとしてデファクトスタンダードと言える存在&lt;br /&gt;
*主なライブラリ&lt;br /&gt;
**ファイルシステムベースの設定レスルーター&lt;br /&gt;
**サーバーコンポーネント&lt;br /&gt;
**データ取得用fetchメソッド&lt;br /&gt;
**リソース組み込みの自動最適化&lt;br /&gt;
**CSSフレームワーク、Tailwind　CSSへの標準対応&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=導入=&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
newdelhi:Workspaces piroto$ npx create-next-app@latest&lt;br /&gt;
Need to install the following packages:&lt;br /&gt;
create-next-app@14.2.14&lt;br /&gt;
Ok to proceed? (y) y&lt;br /&gt;
&lt;br /&gt;
✔ What is your project named? … first-nextjs-app&lt;br /&gt;
✔ Would you like to use TypeScript? … No / Yes&lt;br /&gt;
✔ Would you like to use ESLint? … No / Yes&lt;br /&gt;
✔ Would you like to use Tailwind CSS? … No / Yes&lt;br /&gt;
✔ Would you like to use `src/` directory? … No / Yes&lt;br /&gt;
✔ Would you like to use App Router? (recommended) … No / Yes&lt;br /&gt;
✔ Would you like to customize the default import alias (@/*)? … No / Yes&lt;br /&gt;
Creating a new Next.js app in /Users/piroto/Workspaces/first-nextjs-app.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==実行==&lt;br /&gt;
===開発===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
npm run dev&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Start_next_js.png | 300px]]&lt;br /&gt;
&lt;br /&gt;
===本番ビルド＋実行===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
npm run build&lt;br /&gt;
npm start&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==App Router==&lt;br /&gt;
*React Routerとは異なる独自のルーターを標準で提供&lt;br /&gt;
*コンポーネントそのものはReactと変わらない&lt;br /&gt;
&lt;br /&gt;
===2種類のルーター===&lt;br /&gt;
&lt;br /&gt;
*Pages Router : 旧来から提供されている&lt;br /&gt;
*App Router : Next.js 13から導入された新しいルーター(推奨)&lt;br /&gt;
&lt;br /&gt;
====App Router====&lt;br /&gt;
*フォルダベースのルーター&lt;br /&gt;
*ルート定義不要、フォルダ階層に準じてリクエストパスとコンポーネント(.jsファイル)との対応関係が決まる&lt;br /&gt;
*page.jsはファイル名も固定でフォルダー構造だけでリクエストパスが決定される&lt;br /&gt;
&lt;br /&gt;
=====アプリ共通の外枠=====&lt;br /&gt;
*layout.js&lt;br /&gt;
*&amp;amp;lt;html&amp;amp;gt;、&amp;amp;lt;body&amp;amp;gt; 要素が存在し、個々のページを埋め込むため chilrenプロパティを引用していることが条件&lt;br /&gt;
&lt;br /&gt;
===ルートパラメータ===&lt;br /&gt;
*[名前] ： 単一パラメータ&lt;br /&gt;
*[...名前] : キャッチオールセグメント&lt;br /&gt;
*&amp;lt;nowiki&amp;gt;[[...名前]]&amp;lt;/nowiki&amp;gt; : 省略可能なキャッチオールセグメント&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ App Routerのルートパラメータ&lt;br /&gt;
|-&lt;br /&gt;
! フォルダ階層 !! 対応リクエスト !! パラメータ&lt;br /&gt;
|-&lt;br /&gt;
| /app/hoge/[id]/page.js || /hoge/001 || { id : '001' }&lt;br /&gt;
|-&lt;br /&gt;
| /app/foo/[...keys]/page.js || /foo/aaa/bbb || { keys: ['aaa', 'bbb'] }&lt;br /&gt;
|-&lt;br /&gt;
| /app/bar/&amp;lt;nowiki&amp;gt;[[...keys]]&amp;lt;/nowiki&amp;gt;/page.js || /bar || {}&lt;br /&gt;
|-&lt;br /&gt;
| 〃 || /bar/aaa/bbb || { keys: ['aaa', 'bbb'] }&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Tailwind CSS==&lt;br /&gt;
*https://tailwindcss.com/&lt;br /&gt;
*ユーティリティファーストをコンセプトに開発されたCSSフレームワーク&lt;br /&gt;
*ユーティリティを組み合わせてデザインを作るので独自のスタイルを作りやすく細かな調整もしやすいメリット&lt;br /&gt;
*標準のサイズ、カラーなどは用意されている&lt;br /&gt;
&lt;br /&gt;
[https://tailwindcsscheatsheet.com/ Cheat Sheet]&lt;br /&gt;
&lt;br /&gt;
*Tailwind　CSSによるスタイルを適用&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import &amp;quot;./globals.css&amp;quot;;&lt;br /&gt;
    :&lt;br /&gt;
&lt;br /&gt;
&amp;amp;lt;ul className=&amp;quot;fle bg-blue-600 mb-4 pl-2&amp;quot;&amp;amp;gt;...&amp;amp;lt;/ul&amp;amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Prisma==&lt;br /&gt;
*JavaScriptアプリからデータベース操作を取り持つO/Rマッパー&lt;br /&gt;
===インストール===&lt;br /&gt;
*成功すると以下のファイルが生成される&lt;br /&gt;
**.env : 環境変数ファイル、gitignore に追加する&lt;br /&gt;
** prisma/schema.prisma : Prismaのスキーマファイル&lt;br /&gt;
&lt;br /&gt;
sqliteでの構成例&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ npm install prisma --save-dev&lt;br /&gt;
 $ npx prisma init --datasource-provider sqlite&lt;br /&gt;
 warn You already have a .gitignore file. Don't forget to add `.env` in it to not commit any private information.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===データモデルの定義===&lt;br /&gt;
*prisma/schema.prisma に追記&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
model　reviews {&lt;br /&gt;
  id          String @id&lt;br /&gt;
  title       String&lt;br /&gt;
  author      String&lt;br /&gt;
  price       Int&lt;br /&gt;
  publlisher  String&lt;br /&gt;
  published   String&lt;br /&gt;
  image       String&lt;br /&gt;
  read        DateTime  @default(now())&lt;br /&gt;
  memo        String&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*DBに反映&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ npx prisma db push&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Prisma Studio(Webベース管理ツール)で確認&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ npx prisma studio&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Error: @prisma/client did not initialize yet. Please run &amp;quot;prisma generate&amp;quot; and try to import it again.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ nps prisma generate&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import { PrismaClient } from &amp;quot;@prisma/client&amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Prisma Clientの利用&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import { PrismaClient } from &amp;quot;@prisma/client&amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==サーバーアクション==&lt;br /&gt;
*Next.js内蔵の仕組み&lt;br /&gt;
*ページコンポーネント、イベントハンドラー、&amp;amp;lt;form&amp;amp;lt;要素のaction属性などからサーバーコードを呼び出す仕組み&lt;br /&gt;
*サーバーとのやりとりに際し、fetchなどの非同期通信コードの不要となり、例えばコンポーネントからデータベースを操作するにも直感的なコードを記述できる&lt;br /&gt;
*現時点ではα版&lt;br /&gt;
&lt;br /&gt;
===有効化===&lt;br /&gt;
&lt;br /&gt;
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]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
const nextConfig = {&lt;br /&gt;
    experimental: {&lt;br /&gt;
        serverActions: true&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==実装==&lt;br /&gt;
&lt;br /&gt;
===ルートレイアウト===&lt;br /&gt;
====アプリ内のリンクにはLinkコンポーネントを利用====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import Link from &amp;quot;next/link&amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
規定で以下のようなコンポーネントが用意されており、アプリ内リソースを効率的に利用できる&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ コンポーネント&lt;br /&gt;
|-&lt;br /&gt;
! コンポーネント !! 概要&lt;br /&gt;
|-&lt;br /&gt;
| &amp;amp;lt;Link&amp;amp;gt; || リンクを生成&lt;br /&gt;
|-&lt;br /&gt;
| &amp;amp;lt;Script&amp;amp;gt; || スクリプトのロード&lt;br /&gt;
|-&lt;br /&gt;
| &amp;amp;lt;Image&amp;amp;gt; || 画像を表示&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
====メタデータ====&lt;br /&gt;
*メタデータを定義しておくことで、個々のページに適切なヘッダーなどを埋め込める&lt;br /&gt;
*複数箇所で宣言された場合、シャローマージされる&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
export const metadata: Metadata = {&lt;br /&gt;
  title: &amp;quot;Reading Recorder&amp;quot;,&lt;br /&gt;
  description: &amp;quot;自分が読んだ書籍の記録を残す&amp;quot;,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*generateMetadata関数を利用しデータベースなどから取得した結果を元に動的に生成も可能&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
export async function generateMetadata({ params, searchParams }) {&lt;br /&gt;
    :&lt;br /&gt;
    return {&lt;br /&gt;
        title : result.title,&lt;br /&gt;
            :&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==フォント==&lt;br /&gt;
*Googleフォント(無償フォントのディレクトリサービス)を有効化&lt;br /&gt;
*具体的なフォントはGoogleフォントから自由に選択できるが一般的にはバリアブルフォント推奨(下例ではInconsolata)&lt;br /&gt;
*フォントはファイルサイズが大きいので、subsetで利用する文字のみ取り出す&lt;br /&gt;
*fnc.className でフォントを適用できる&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import { Inconsolata } from 'next/font/google';&lt;br /&gt;
const fnt = Inconsolata({ subsets: ['latin'] });&lt;br /&gt;
&lt;br /&gt;
  :&lt;br /&gt;
&amp;amp;lt;body className={`${fnt.className}` }&amp;amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==MUI==&lt;br /&gt;
[[MUI]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Tips==&lt;br /&gt;
&lt;br /&gt;
===リモートホストからの画像表示を許可する===&lt;br /&gt;
*next.config.mjs&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
const nextConfig = {&lt;br /&gt;
&lt;br /&gt;
    :&lt;br /&gt;
&lt;br /&gt;
    images: {&lt;br /&gt;
        remotePatterns: [&lt;br /&gt;
            {&lt;br /&gt;
                hostname: 'books.google.com'&lt;br /&gt;
            } &lt;br /&gt;
        ] &lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Piroto</name></author>
		
	</entry>
	<entry>
		<id>https://www.typea.info/tips_/index.php?title=Next.js&amp;diff=35334</id>
		<title>Next.js</title>
		<link rel="alternate" type="text/html" href="https://www.typea.info/tips_/index.php?title=Next.js&amp;diff=35334"/>
		<updated>2024-10-05T09:44:16Z</updated>

		<summary type="html">&lt;p&gt;Piroto: /* データモデルの定義 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[React]] | [[MUI]] |&lt;br /&gt;
&lt;br /&gt;
{{amazon|4815619484}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Reactは、あくまでUI部分のみ&lt;br /&gt;
*本格的なアプリ開発には周辺領域を担うためのフレームワークが必要&lt;br /&gt;
*Reactベースのフレームワークとしてデファクトスタンダードと言える存在&lt;br /&gt;
*主なライブラリ&lt;br /&gt;
**ファイルシステムベースの設定レスルーター&lt;br /&gt;
**サーバーコンポーネント&lt;br /&gt;
**データ取得用fetchメソッド&lt;br /&gt;
**リソース組み込みの自動最適化&lt;br /&gt;
**CSSフレームワーク、Tailwind　CSSへの標準対応&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=導入=&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
newdelhi:Workspaces piroto$ npx create-next-app@latest&lt;br /&gt;
Need to install the following packages:&lt;br /&gt;
create-next-app@14.2.14&lt;br /&gt;
Ok to proceed? (y) y&lt;br /&gt;
&lt;br /&gt;
✔ What is your project named? … first-nextjs-app&lt;br /&gt;
✔ Would you like to use TypeScript? … No / Yes&lt;br /&gt;
✔ Would you like to use ESLint? … No / Yes&lt;br /&gt;
✔ Would you like to use Tailwind CSS? … No / Yes&lt;br /&gt;
✔ Would you like to use `src/` directory? … No / Yes&lt;br /&gt;
✔ Would you like to use App Router? (recommended) … No / Yes&lt;br /&gt;
✔ Would you like to customize the default import alias (@/*)? … No / Yes&lt;br /&gt;
Creating a new Next.js app in /Users/piroto/Workspaces/first-nextjs-app.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==実行==&lt;br /&gt;
===開発===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
npm run dev&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Start_next_js.png | 300px]]&lt;br /&gt;
&lt;br /&gt;
===本番ビルド＋実行===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
npm run build&lt;br /&gt;
npm start&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==App Router==&lt;br /&gt;
*React Routerとは異なる独自のルーターを標準で提供&lt;br /&gt;
*コンポーネントそのものはReactと変わらない&lt;br /&gt;
&lt;br /&gt;
===2種類のルーター===&lt;br /&gt;
&lt;br /&gt;
*Pages Router : 旧来から提供されている&lt;br /&gt;
*App Router : Next.js 13から導入された新しいルーター(推奨)&lt;br /&gt;
&lt;br /&gt;
====App Router====&lt;br /&gt;
*フォルダベースのルーター&lt;br /&gt;
*ルート定義不要、フォルダ階層に準じてリクエストパスとコンポーネント(.jsファイル)との対応関係が決まる&lt;br /&gt;
*page.jsはファイル名も固定でフォルダー構造だけでリクエストパスが決定される&lt;br /&gt;
&lt;br /&gt;
=====アプリ共通の外枠=====&lt;br /&gt;
*layout.js&lt;br /&gt;
*&amp;amp;lt;html&amp;amp;gt;、&amp;amp;lt;body&amp;amp;gt; 要素が存在し、個々のページを埋め込むため chilrenプロパティを引用していることが条件&lt;br /&gt;
&lt;br /&gt;
===ルートパラメータ===&lt;br /&gt;
*[名前] ： 単一パラメータ&lt;br /&gt;
*[...名前] : キャッチオールセグメント&lt;br /&gt;
*&amp;lt;nowiki&amp;gt;[[...名前]]&amp;lt;/nowiki&amp;gt; : 省略可能なキャッチオールセグメント&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ App Routerのルートパラメータ&lt;br /&gt;
|-&lt;br /&gt;
! フォルダ階層 !! 対応リクエスト !! パラメータ&lt;br /&gt;
|-&lt;br /&gt;
| /app/hoge/[id]/page.js || /hoge/001 || { id : '001' }&lt;br /&gt;
|-&lt;br /&gt;
| /app/foo/[...keys]/page.js || /foo/aaa/bbb || { keys: ['aaa', 'bbb'] }&lt;br /&gt;
|-&lt;br /&gt;
| /app/bar/&amp;lt;nowiki&amp;gt;[[...keys]]&amp;lt;/nowiki&amp;gt;/page.js || /bar || {}&lt;br /&gt;
|-&lt;br /&gt;
| 〃 || /bar/aaa/bbb || { keys: ['aaa', 'bbb'] }&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Tailwind CSS==&lt;br /&gt;
*https://tailwindcss.com/&lt;br /&gt;
*ユーティリティファーストをコンセプトに開発されたCSSフレームワーク&lt;br /&gt;
*ユーティリティを組み合わせてデザインを作るので独自のスタイルを作りやすく細かな調整もしやすいメリット&lt;br /&gt;
*標準のサイズ、カラーなどは用意されている&lt;br /&gt;
&lt;br /&gt;
[https://tailwindcsscheatsheet.com/ Cheat Sheet]&lt;br /&gt;
&lt;br /&gt;
*Tailwind　CSSによるスタイルを適用&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import &amp;quot;./globals.css&amp;quot;;&lt;br /&gt;
    :&lt;br /&gt;
&lt;br /&gt;
&amp;amp;lt;ul className=&amp;quot;fle bg-blue-600 mb-4 pl-2&amp;quot;&amp;amp;gt;...&amp;amp;lt;/ul&amp;amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Prisma==&lt;br /&gt;
*JavaScriptアプリからデータベース操作を取り持つO/Rマッパー&lt;br /&gt;
===インストール===&lt;br /&gt;
*成功すると以下のファイルが生成される&lt;br /&gt;
**.env : 環境変数ファイル、gitignore に追加する&lt;br /&gt;
** prisma/schema.prisma : Prismaのスキーマファイル&lt;br /&gt;
&lt;br /&gt;
sqliteでの構成例&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ npm install prisma --save-dev&lt;br /&gt;
 $ npx prisma init --datasource-provider sqlite&lt;br /&gt;
 warn You already have a .gitignore file. Don't forget to add `.env` in it to not commit any private information.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===データモデルの定義===&lt;br /&gt;
*prisma/schema.prisma に追記&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
model　reviews {&lt;br /&gt;
  id          String @id&lt;br /&gt;
  title       String&lt;br /&gt;
  author      String&lt;br /&gt;
  price       Int&lt;br /&gt;
  publlisher  String&lt;br /&gt;
  published   String&lt;br /&gt;
  image       String&lt;br /&gt;
  read        DateTime  @default(now())&lt;br /&gt;
  memo        String&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*DBに反映&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ npx prisma db push&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Prisma Studio(Webベース管理ツール)で確認&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ npx prisma studio&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Error: @prisma/client did not initialize yet. Please run &amp;quot;prisma generate&amp;quot; and try to import it again.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ nps prisma generate&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import { PrismaClient } from &amp;quot;@prisma/client&amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Prisma Clientの利用&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import { PrismaClient } from &amp;quot;@prisma/client&amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==サーバーアクション==&lt;br /&gt;
*Next.js内蔵の仕組み&lt;br /&gt;
*ページコンポーネント、イベントハンドラー、&amp;amp;lt;form&amp;amp;lt;要素のaction属性などからサーバーコードを呼び出す仕組み&lt;br /&gt;
*サーバーとのやりとりに際し、fetchなどの非同期通信コードの不要となり、例えばコンポーネントからデータベースを操作するにも直感的なコードを記述できる&lt;br /&gt;
*現時点ではα版&lt;br /&gt;
&lt;br /&gt;
===有効化===&lt;br /&gt;
&lt;br /&gt;
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]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
const nextConfig = {&lt;br /&gt;
    experimental: {&lt;br /&gt;
        serverActions: true&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==実装==&lt;br /&gt;
&lt;br /&gt;
===ルートレイアウト===&lt;br /&gt;
====アプリ内のリンクにはLinkコンポーネントを利用====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import Link from &amp;quot;next/link&amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
規定で以下のようなコンポーネントが用意されており、アプリ内リソースを効率的に利用できる&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ コンポーネント&lt;br /&gt;
|-&lt;br /&gt;
! コンポーネント !! 概要&lt;br /&gt;
|-&lt;br /&gt;
| &amp;amp;lt;Link&amp;amp;gt; || リンクを生成&lt;br /&gt;
|-&lt;br /&gt;
| &amp;amp;lt;Script&amp;amp;gt; || スクリプトのロード&lt;br /&gt;
|-&lt;br /&gt;
| &amp;amp;lt;Image&amp;amp;gt; || 画像を表示&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
====メタデータ====&lt;br /&gt;
*メタデータを定義しておくことで、個々のページに適切なヘッダーなどを埋め込める&lt;br /&gt;
*複数箇所で宣言された場合、シャローマージされる&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
export const metadata: Metadata = {&lt;br /&gt;
  title: &amp;quot;Reading Recorder&amp;quot;,&lt;br /&gt;
  description: &amp;quot;自分が読んだ書籍の記録を残す&amp;quot;,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*generateMetadata関数を利用しデータベースなどから取得した結果を元に動的に生成も可能&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
export async function generateMetadata({ params, searchParams }) {&lt;br /&gt;
    :&lt;br /&gt;
    return {&lt;br /&gt;
        title : result.title,&lt;br /&gt;
            :&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==フォント==&lt;br /&gt;
*Googleフォント(無償フォントのディレクトリサービス)を有効化&lt;br /&gt;
*具体的なフォントはGoogleフォントから自由に選択できるが一般的にはバリアブルフォント推奨(下例ではInconsolata)&lt;br /&gt;
*フォントはファイルサイズが大きいので、subsetで利用する文字のみ取り出す&lt;br /&gt;
*fnc.className でフォントを適用できる&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import { Inconsolata } from 'next/font/google';&lt;br /&gt;
const fnt = Inconsolata({ subsets: ['latin'] });&lt;br /&gt;
&lt;br /&gt;
  :&lt;br /&gt;
&amp;amp;lt;body className={`${fnt.className}` }&amp;amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==MUI==&lt;br /&gt;
[[MUI]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Tips==&lt;br /&gt;
&lt;br /&gt;
===リモートホストからの画像表示を許可する===&lt;br /&gt;
*next.config.mjs&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
const nextConfig = {&lt;br /&gt;
&lt;br /&gt;
    :&lt;br /&gt;
&lt;br /&gt;
    images: {&lt;br /&gt;
        remotePatterns: [&lt;br /&gt;
            {&lt;br /&gt;
                hostname: 'books.google.com'&lt;br /&gt;
            } &lt;br /&gt;
        ] &lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Piroto</name></author>
		
	</entry>
	<entry>
		<id>https://www.typea.info/tips_/index.php?title=Next.js&amp;diff=35333</id>
		<title>Next.js</title>
		<link rel="alternate" type="text/html" href="https://www.typea.info/tips_/index.php?title=Next.js&amp;diff=35333"/>
		<updated>2024-10-05T09:18:29Z</updated>

		<summary type="html">&lt;p&gt;Piroto: /* MUI */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[React]] | [[MUI]] |&lt;br /&gt;
&lt;br /&gt;
{{amazon|4815619484}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Reactは、あくまでUI部分のみ&lt;br /&gt;
*本格的なアプリ開発には周辺領域を担うためのフレームワークが必要&lt;br /&gt;
*Reactベースのフレームワークとしてデファクトスタンダードと言える存在&lt;br /&gt;
*主なライブラリ&lt;br /&gt;
**ファイルシステムベースの設定レスルーター&lt;br /&gt;
**サーバーコンポーネント&lt;br /&gt;
**データ取得用fetchメソッド&lt;br /&gt;
**リソース組み込みの自動最適化&lt;br /&gt;
**CSSフレームワーク、Tailwind　CSSへの標準対応&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=導入=&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
newdelhi:Workspaces piroto$ npx create-next-app@latest&lt;br /&gt;
Need to install the following packages:&lt;br /&gt;
create-next-app@14.2.14&lt;br /&gt;
Ok to proceed? (y) y&lt;br /&gt;
&lt;br /&gt;
✔ What is your project named? … first-nextjs-app&lt;br /&gt;
✔ Would you like to use TypeScript? … No / Yes&lt;br /&gt;
✔ Would you like to use ESLint? … No / Yes&lt;br /&gt;
✔ Would you like to use Tailwind CSS? … No / Yes&lt;br /&gt;
✔ Would you like to use `src/` directory? … No / Yes&lt;br /&gt;
✔ Would you like to use App Router? (recommended) … No / Yes&lt;br /&gt;
✔ Would you like to customize the default import alias (@/*)? … No / Yes&lt;br /&gt;
Creating a new Next.js app in /Users/piroto/Workspaces/first-nextjs-app.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==実行==&lt;br /&gt;
===開発===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
npm run dev&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Start_next_js.png | 300px]]&lt;br /&gt;
&lt;br /&gt;
===本番ビルド＋実行===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
npm run build&lt;br /&gt;
npm start&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==App Router==&lt;br /&gt;
*React Routerとは異なる独自のルーターを標準で提供&lt;br /&gt;
*コンポーネントそのものはReactと変わらない&lt;br /&gt;
&lt;br /&gt;
===2種類のルーター===&lt;br /&gt;
&lt;br /&gt;
*Pages Router : 旧来から提供されている&lt;br /&gt;
*App Router : Next.js 13から導入された新しいルーター(推奨)&lt;br /&gt;
&lt;br /&gt;
====App Router====&lt;br /&gt;
*フォルダベースのルーター&lt;br /&gt;
*ルート定義不要、フォルダ階層に準じてリクエストパスとコンポーネント(.jsファイル)との対応関係が決まる&lt;br /&gt;
*page.jsはファイル名も固定でフォルダー構造だけでリクエストパスが決定される&lt;br /&gt;
&lt;br /&gt;
=====アプリ共通の外枠=====&lt;br /&gt;
*layout.js&lt;br /&gt;
*&amp;amp;lt;html&amp;amp;gt;、&amp;amp;lt;body&amp;amp;gt; 要素が存在し、個々のページを埋め込むため chilrenプロパティを引用していることが条件&lt;br /&gt;
&lt;br /&gt;
===ルートパラメータ===&lt;br /&gt;
*[名前] ： 単一パラメータ&lt;br /&gt;
*[...名前] : キャッチオールセグメント&lt;br /&gt;
*&amp;lt;nowiki&amp;gt;[[...名前]]&amp;lt;/nowiki&amp;gt; : 省略可能なキャッチオールセグメント&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ App Routerのルートパラメータ&lt;br /&gt;
|-&lt;br /&gt;
! フォルダ階層 !! 対応リクエスト !! パラメータ&lt;br /&gt;
|-&lt;br /&gt;
| /app/hoge/[id]/page.js || /hoge/001 || { id : '001' }&lt;br /&gt;
|-&lt;br /&gt;
| /app/foo/[...keys]/page.js || /foo/aaa/bbb || { keys: ['aaa', 'bbb'] }&lt;br /&gt;
|-&lt;br /&gt;
| /app/bar/&amp;lt;nowiki&amp;gt;[[...keys]]&amp;lt;/nowiki&amp;gt;/page.js || /bar || {}&lt;br /&gt;
|-&lt;br /&gt;
| 〃 || /bar/aaa/bbb || { keys: ['aaa', 'bbb'] }&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Tailwind CSS==&lt;br /&gt;
*https://tailwindcss.com/&lt;br /&gt;
*ユーティリティファーストをコンセプトに開発されたCSSフレームワーク&lt;br /&gt;
*ユーティリティを組み合わせてデザインを作るので独自のスタイルを作りやすく細かな調整もしやすいメリット&lt;br /&gt;
*標準のサイズ、カラーなどは用意されている&lt;br /&gt;
&lt;br /&gt;
[https://tailwindcsscheatsheet.com/ Cheat Sheet]&lt;br /&gt;
&lt;br /&gt;
*Tailwind　CSSによるスタイルを適用&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import &amp;quot;./globals.css&amp;quot;;&lt;br /&gt;
    :&lt;br /&gt;
&lt;br /&gt;
&amp;amp;lt;ul className=&amp;quot;fle bg-blue-600 mb-4 pl-2&amp;quot;&amp;amp;gt;...&amp;amp;lt;/ul&amp;amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Prisma==&lt;br /&gt;
*JavaScriptアプリからデータベース操作を取り持つO/Rマッパー&lt;br /&gt;
===インストール===&lt;br /&gt;
*成功すると以下のファイルが生成される&lt;br /&gt;
**.env : 環境変数ファイル、gitignore に追加する&lt;br /&gt;
** prisma/schema.prisma : Prismaのスキーマファイル&lt;br /&gt;
&lt;br /&gt;
sqliteでの構成例&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ npm install prisma --save-dev&lt;br /&gt;
 $ npx prisma init --datasource-provider sqlite&lt;br /&gt;
 warn You already have a .gitignore file. Don't forget to add `.env` in it to not commit any private information.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===データモデルの定義===&lt;br /&gt;
*prisma/schema.prisma に追記&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
model　reviews {&lt;br /&gt;
  id          String @id&lt;br /&gt;
  title       String&lt;br /&gt;
  author      String&lt;br /&gt;
  price       Int&lt;br /&gt;
  publlisher  String&lt;br /&gt;
  published   String&lt;br /&gt;
  image       String&lt;br /&gt;
  read        DateTime  @default(now())&lt;br /&gt;
  memo        String&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*DBに反映&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ npx prisma db push&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Prisma Studio(Webベース管理ツール)で確認&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ npx prisma studio&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==サーバーアクション==&lt;br /&gt;
*Next.js内蔵の仕組み&lt;br /&gt;
*ページコンポーネント、イベントハンドラー、&amp;amp;lt;form&amp;amp;lt;要素のaction属性などからサーバーコードを呼び出す仕組み&lt;br /&gt;
*サーバーとのやりとりに際し、fetchなどの非同期通信コードの不要となり、例えばコンポーネントからデータベースを操作するにも直感的なコードを記述できる&lt;br /&gt;
*現時点ではα版&lt;br /&gt;
&lt;br /&gt;
===有効化===&lt;br /&gt;
&lt;br /&gt;
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]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
const nextConfig = {&lt;br /&gt;
    experimental: {&lt;br /&gt;
        serverActions: true&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==実装==&lt;br /&gt;
&lt;br /&gt;
===ルートレイアウト===&lt;br /&gt;
====アプリ内のリンクにはLinkコンポーネントを利用====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import Link from &amp;quot;next/link&amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
規定で以下のようなコンポーネントが用意されており、アプリ内リソースを効率的に利用できる&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ コンポーネント&lt;br /&gt;
|-&lt;br /&gt;
! コンポーネント !! 概要&lt;br /&gt;
|-&lt;br /&gt;
| &amp;amp;lt;Link&amp;amp;gt; || リンクを生成&lt;br /&gt;
|-&lt;br /&gt;
| &amp;amp;lt;Script&amp;amp;gt; || スクリプトのロード&lt;br /&gt;
|-&lt;br /&gt;
| &amp;amp;lt;Image&amp;amp;gt; || 画像を表示&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
====メタデータ====&lt;br /&gt;
*メタデータを定義しておくことで、個々のページに適切なヘッダーなどを埋め込める&lt;br /&gt;
*複数箇所で宣言された場合、シャローマージされる&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
export const metadata: Metadata = {&lt;br /&gt;
  title: &amp;quot;Reading Recorder&amp;quot;,&lt;br /&gt;
  description: &amp;quot;自分が読んだ書籍の記録を残す&amp;quot;,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*generateMetadata関数を利用しデータベースなどから取得した結果を元に動的に生成も可能&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
export async function generateMetadata({ params, searchParams }) {&lt;br /&gt;
    :&lt;br /&gt;
    return {&lt;br /&gt;
        title : result.title,&lt;br /&gt;
            :&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==フォント==&lt;br /&gt;
*Googleフォント(無償フォントのディレクトリサービス)を有効化&lt;br /&gt;
*具体的なフォントはGoogleフォントから自由に選択できるが一般的にはバリアブルフォント推奨(下例ではInconsolata)&lt;br /&gt;
*フォントはファイルサイズが大きいので、subsetで利用する文字のみ取り出す&lt;br /&gt;
*fnc.className でフォントを適用できる&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import { Inconsolata } from 'next/font/google';&lt;br /&gt;
const fnt = Inconsolata({ subsets: ['latin'] });&lt;br /&gt;
&lt;br /&gt;
  :&lt;br /&gt;
&amp;amp;lt;body className={`${fnt.className}` }&amp;amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==MUI==&lt;br /&gt;
[[MUI]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Tips==&lt;br /&gt;
&lt;br /&gt;
===リモートホストからの画像表示を許可する===&lt;br /&gt;
*next.config.mjs&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
const nextConfig = {&lt;br /&gt;
&lt;br /&gt;
    :&lt;br /&gt;
&lt;br /&gt;
    images: {&lt;br /&gt;
        remotePatterns: [&lt;br /&gt;
            {&lt;br /&gt;
                hostname: 'books.google.com'&lt;br /&gt;
            } &lt;br /&gt;
        ] &lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Piroto</name></author>
		
	</entry>
	<entry>
		<id>https://www.typea.info/tips_/index.php?title=React&amp;diff=35332</id>
		<title>React</title>
		<link rel="alternate" type="text/html" href="https://www.typea.info/tips_/index.php?title=React&amp;diff=35332"/>
		<updated>2024-10-05T08:54:13Z</updated>

		<summary type="html">&lt;p&gt;Piroto: /* ファイル拡張子 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==[[React]]==&lt;br /&gt;
[[Node.js]] | [[Next.js]] |&lt;br /&gt;
&lt;br /&gt;
{{amazon|4873117887}}&lt;br /&gt;
&lt;br /&gt;
{{amazon|4815619484}}&lt;br /&gt;
&lt;br /&gt;
===スケルトン作成===&lt;br /&gt;
#[https://www.typea.info/blog/index.php/2017/08/15/react_1/ 開発の全体像を把握しつつ開発環境を整える]&lt;br /&gt;
#[https://www.typea.info/blog/index.php/2017/08/16/react_router/ React の単純なサンプルに React Router を適用する]&lt;br /&gt;
#[https://www.typea.info/blog/index.php/2017/08/17/react_react_router_redux-saga/ React の単純なサンプルに React Router を組み込んだものに Redux-Saga を適用する]&lt;br /&gt;
#[https://www.typea.info/blog/index.php/2017/08/19/react_react_router_redux-saga_ajax/ React の単純なサンプルに React Router を組み込んだものに Redux-Saga を適用したものからAjax通信を組み込む]&lt;br /&gt;
#[https://www.typea.info/blog/index.php/2017/08/23/react-react_router-redux-saga-superagent_bootstrap/ React環境-&amp;amp;gt;React Router-&amp;amp;gt;Redux-Saga-&amp;amp;gt;SuperAgent に Bootstrapを適用する]&lt;br /&gt;
&lt;br /&gt;
==導入==&lt;br /&gt;
&lt;br /&gt;
===Create React App===&lt;br /&gt;
*Reactアプリ開発のためのコマンドラインツール。トランスパイラ、バンドラ、開発サーバーなどを含むツールチェーン&lt;br /&gt;
*Facebook本家が提供。他にもNext.js、Vite、Gatsby、Parcelなどのツールチェーンがある。&lt;br /&gt;
*より高度な環境としてNext.jsも存在&lt;br /&gt;
&lt;br /&gt;
===Next.js===&lt;br /&gt;
*[[Next.js]]&lt;br /&gt;
*Reactは、あくまでUI部分のみ&lt;br /&gt;
*本格的なアプリ開発には周辺領域を担うためのフレームワークが必要&lt;br /&gt;
*Reactベースのフレームワークとしてデファクトスタンダードと言える存在&lt;br /&gt;
*主なライブラリ&lt;br /&gt;
**ファイルシステムベースの設定レスルーター&lt;br /&gt;
**サーバーコンポーネント&lt;br /&gt;
**データ取得用fetchメソッド&lt;br /&gt;
**リソース組み込みの自動最適化&lt;br /&gt;
**CSSフレームワーク、Tailwind　CSSへの標準対応&lt;br /&gt;
&lt;br /&gt;
===Node===&lt;br /&gt;
[[Node.js]] のインストール&lt;br /&gt;
&lt;br /&gt;
====npx====&lt;br /&gt;
*ローカルにインストールされたツールを実行するためのパッケージランナー&lt;br /&gt;
&lt;br /&gt;
===Next.jsアプリの作成===&lt;br /&gt;
[[Next.js]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===[[TypeScript]]の導入===&lt;br /&gt;
====ファイル拡張子====&lt;br /&gt;
&lt;br /&gt;
=====JSX=====&lt;br /&gt;
*https://3chome.net/javascript-typescript/#:~:text=.tsx%EF%BC%88TSX%E3%83%95%E3%82%A1&lt;br /&gt;
*[[TypeScript]]の拡張子&lt;br /&gt;
**.ts :　コードにJSX含まない&lt;br /&gt;
**.tsx :　コードにJSX含む(含まない場合tsxとしてもよいが望ましくない)&lt;br /&gt;
&lt;br /&gt;
=====Module=====&lt;br /&gt;
*https://zenn.dev/uhyo/articles/typescript-module-option&lt;br /&gt;
**.mts&lt;br /&gt;
&lt;br /&gt;
====型アサーション====&lt;br /&gt;
&lt;br /&gt;
===導入(旧)===&lt;br /&gt;
----&lt;br /&gt;
*https://facebook.github.io/react/docs/installation.html&lt;br /&gt;
*https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/[[R]]EADME.md#table-of-contents&lt;br /&gt;
*[[React]]のSPAを作成するのによい方法&lt;br /&gt;
 [[npm]] install -g create-react-app&lt;br /&gt;
*https://ja.reactjs.org/docs/create-a-new-react-app.html&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
npx create-react-app my-app&lt;br /&gt;
cd my-app&lt;br /&gt;
npm start&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
*[[React]]はバックエンドロジックやデータベースを持たないが、使いたいものを使えばよい。&lt;br /&gt;
*Babelやwebpackのようなビルドツールも設定なしに利用できる。&lt;br /&gt;
 PS C:\workspaces\vscode\reactlesson&amp;amp;gt; create-react-app react-lesson&lt;br /&gt;
 Creating a new [[React]] app in C:\workspaces\vscode\reactlesson\react-lesson.&lt;br /&gt;
 &lt;br /&gt;
 Installing packages. This might take a couple minutes.&lt;br /&gt;
 Installing react, react-dom, and react-scripts...&lt;br /&gt;
               :&lt;br /&gt;
*アプリケーションが作成されたら実行&lt;br /&gt;
 PS C:\workspaces\vscode\reactlesson&amp;amp;gt; cd react-lesson&lt;br /&gt;
 PS C:\workspaces\vscode\reactlesson&amp;amp;gt; [[npm]] start&lt;br /&gt;
*実行された&lt;br /&gt;
[[File:1086_react01.jpg]]&lt;br /&gt;
*/src/App.js を書き換えてみる&lt;br /&gt;
 import [[React]], { Component } from 'react';&lt;br /&gt;
 import logo from './logo.svg';&lt;br /&gt;
 import './App.css';&lt;br /&gt;
 &lt;br /&gt;
 const element = (&amp;amp;lt;h1&amp;amp;gt;Hello,world&amp;amp;lt;/h1&amp;amp;gt;);&lt;br /&gt;
 class App extends Component {&lt;br /&gt;
   render() {&lt;br /&gt;
     return (&lt;br /&gt;
       element&lt;br /&gt;
     );&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 export default App;&lt;br /&gt;
*反映された&lt;br /&gt;
[[File:1087_react02.jpg]]&lt;br /&gt;
*リリース準備ができたら、以下を実行することで、buildフォルダ以下に最適化されたアプリケーションを作成する&lt;br /&gt;
 [[npm]] run build&lt;br /&gt;
&lt;br /&gt;
==クイックスタート==&lt;br /&gt;
===JSX===&lt;br /&gt;
 const element = &amp;amp;lt;h1&amp;amp;gt;Hello,world!&amp;amp;lt;/h1&amp;amp;gt;;&lt;br /&gt;
*文字列でも、[[HTML]]でもなく、JSX&lt;br /&gt;
*[[JavaScript]]の拡張文法&lt;br /&gt;
*テンプレートと思われるかもしれないが、完全な[[JavaScript]]&lt;br /&gt;
*JSXは[[React]]の要素を生成する&lt;br /&gt;
===JSX表現===&lt;br /&gt;
*どのような[[JavaScript]]の表現も、中括弧で囲むことでJSXに埋め込むことができる&lt;br /&gt;
*const element = (&amp;amp;lt;h1&amp;amp;gt;Hello, {formatName(user)}!&amp;amp;lt;/h1&amp;amp;gt;);&lt;br /&gt;
&lt;br /&gt;
 &amp;amp;lt;!DOCTYPE html&amp;amp;gt;&lt;br /&gt;
 &amp;amp;lt;html&amp;amp;gt;&lt;br /&gt;
   &amp;amp;lt;head&amp;amp;gt;&lt;br /&gt;
     &amp;amp;lt;meta charset=&amp;quot;UTF-8&amp;quot; /&amp;amp;gt;&lt;br /&gt;
     &amp;amp;lt;title&amp;amp;gt;Hello World&amp;amp;lt;/title&amp;amp;gt;&lt;br /&gt;
     &amp;amp;lt;script src=&amp;quot;https://unpkg.com/react@latest/dist/react.js&amp;quot;&amp;amp;gt;&amp;amp;lt;/script&amp;amp;gt;&lt;br /&gt;
     &amp;amp;lt;script src=&amp;quot;https://unpkg.com/react-dom@latest/dist/react-dom.js&amp;quot;&amp;amp;gt;&amp;amp;lt;/script&amp;amp;gt;&lt;br /&gt;
     &amp;amp;lt;script src=&amp;quot;https://unpkg.com/babel-standalone@6.15.0/babel.min.js&amp;quot;&amp;amp;gt;&amp;amp;lt;/script&amp;amp;gt;&lt;br /&gt;
   &amp;amp;lt;/head&amp;amp;gt;&lt;br /&gt;
   &amp;amp;lt;body&amp;amp;gt;&lt;br /&gt;
     &amp;amp;lt;div id=&amp;quot;root&amp;quot;&amp;amp;gt;&amp;amp;lt;/div&amp;amp;gt;&lt;br /&gt;
     &amp;amp;lt;script type=&amp;quot;text/babel&amp;quot;&amp;amp;gt;&lt;br /&gt;
     function formatName(user) {&lt;br /&gt;
         return user.firstName + ' ' + user.lastName;&lt;br /&gt;
     }&lt;br /&gt;
     const user = {firstName:'Hiroto', lastName:'Yagi'};&lt;br /&gt;
     const element = (&amp;amp;lt;h1&amp;amp;gt;Hello, {formatName(user)}!&amp;amp;lt;/h1&amp;amp;gt;); &lt;br /&gt;
     [[React]]DOM.render(&lt;br /&gt;
         element,&lt;br /&gt;
         document.getElementById('root')&lt;br /&gt;
     );&lt;br /&gt;
     &amp;amp;lt;/script&amp;amp;gt;&lt;br /&gt;
   &amp;amp;lt;/body&amp;amp;gt;&lt;br /&gt;
 &amp;amp;lt;/html&amp;amp;gt;&lt;br /&gt;
&lt;br /&gt;
*コンパイルされたJSXは通常の[[JavaScript]]オブジェクト&lt;br /&gt;
*JSXをif文やforループ、変数への割り当て、引数や戻り値に利用できる&lt;br /&gt;
&lt;br /&gt;
 function greeting(user) {&lt;br /&gt;
    var now = new Date();&lt;br /&gt;
    if (5 &amp;amp;lt;= now.getHours() &amp;amp;&amp;amp; now.getHours() &amp;amp;lt;= 12) {&lt;br /&gt;
        return &amp;amp;lt;h1&amp;amp;gt; Good morning {user.firstName + ' ' + user.lastName}.&amp;amp;lt;/h1&amp;amp;gt;;&lt;br /&gt;
    } else {&lt;br /&gt;
        return &amp;amp;lt;h1&amp;amp;gt; Hello {user.firstName + ' ' + user.lastName}.&amp;amp;lt;/h1&amp;amp;gt;;&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
====属性に利用====&lt;br /&gt;
*中括弧を利用して、二重引用符なし(使用すると文字列リテラルとして扱われる)で直接利用できる。&lt;br /&gt;
 &amp;amp;lt;div id=&amp;quot;root&amp;quot;&amp;amp;gt;&amp;amp;lt;/div&amp;amp;gt;&lt;br /&gt;
 &amp;amp;lt;script type=&amp;quot;text/babel&amp;quot;&amp;amp;gt;&lt;br /&gt;
 function greeting(user) {&lt;br /&gt;
     var now = new Date();&lt;br /&gt;
     if (5 &amp;amp;lt;= now.getHours() &amp;amp;&amp;amp; now.getHours() &amp;amp;lt;= 12) {&lt;br /&gt;
         return &amp;amp;lt;h1&amp;amp;gt; Good morning &amp;amp;lt;a href={user.webpageUrl}&amp;amp;gt;{user.firstName + ' ' + user.lastName}&amp;amp;lt;/a&amp;amp;gt;.&amp;amp;lt;/h1&amp;amp;gt;;&lt;br /&gt;
     } else {&lt;br /&gt;
         return &amp;amp;lt;h1&amp;amp;gt; Hello &amp;amp;lt;a href={user.webpageUrl}&amp;amp;gt;{user.firstName + ' ' + user.lastName}&amp;amp;lt;/a&amp;amp;gt;.&amp;amp;lt;/h1&amp;amp;gt;;&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
 const user = {firstName:'Hiroto', lastName:'Yagi', webpageUrl:'http://typea.info'};&lt;br /&gt;
 const element = (&amp;amp;lt;h1&amp;amp;gt;{greeting(user)}&amp;amp;lt;/h1&amp;amp;gt;); &lt;br /&gt;
 [[React]]DOM.render(&lt;br /&gt;
     element,&lt;br /&gt;
     document.getElementById('root')&lt;br /&gt;
 );&lt;br /&gt;
[[File:1089_react04.jpg]]&lt;br /&gt;
====子要素====&lt;br /&gt;
*子要素がない場合、[[XML]]同様　/&amp;amp;gt; で閉じる&lt;br /&gt;
*子要素を含む&lt;br /&gt;
*JSXはHTMLより[[JavaScript]]により近い。ReactDOMはキャメルケースプロパティ(HTMLでは、class がclassName、HTMLではtabindexがtabIndexなど)を持つ&lt;br /&gt;
 function greeting(user) {&lt;br /&gt;
     return &amp;amp;lt;div&amp;amp;gt;&lt;br /&gt;
             &amp;amp;lt;h1&amp;amp;gt; Good morning {user.firstName + ' ' + user.lastName}.&amp;amp;lt;/h1&amp;amp;gt;&lt;br /&gt;
             &amp;amp;lt;h2&amp;amp;gt;&amp;amp;lt;a href={user.webpageUrl}&amp;amp;gt;webpage&amp;amp;lt;/a&amp;amp;gt;&amp;amp;lt;/h2&amp;amp;gt;&lt;br /&gt;
            &amp;amp;lt;/div&amp;amp;gt;&lt;br /&gt;
            ;&lt;br /&gt;
 }&lt;br /&gt;
 const user = {firstName:'Hiroto', lastName:'Yagi', webpageUrl:'http://typea.info'};&lt;br /&gt;
 const element = (greeting(user)); &lt;br /&gt;
 [[React]]DOM.render(&lt;br /&gt;
     element,&lt;br /&gt;
     document.getElementById('root')&lt;br /&gt;
 );&lt;br /&gt;
[[File:1090_react05.jpg]]&lt;br /&gt;
====インジェクション[[攻撃]]の予防====&lt;br /&gt;
*デフォルトで[[React]] DOMは、JSXに埋め込まれた値をレンダリング前にエスケープする&lt;br /&gt;
*明示的にアプリケーションに記述しなくてもインジェクションされないことを保証する&lt;br /&gt;
*XSS[[攻撃]]の予防を助ける&lt;br /&gt;
 function greeting(user, title) {&lt;br /&gt;
     return &amp;amp;lt;div&amp;amp;gt;&lt;br /&gt;
              &amp;amp;lt;h1&amp;amp;gt;{title}&amp;amp;lt;/h1&amp;amp;gt;&lt;br /&gt;
              &amp;amp;lt;h2&amp;amp;gt; Good morning {user.firstName + ' ' + user.lastName}.&amp;amp;lt;/h2&amp;amp;gt;&lt;br /&gt;
              &amp;amp;lt;h2&amp;amp;gt;&amp;amp;lt;a href={user.webpageUrl}&amp;amp;gt;webpage&amp;amp;lt;/a&amp;amp;gt;&amp;amp;lt;/h2&amp;amp;gt;&lt;br /&gt;
            &amp;amp;lt;/div&amp;amp;gt;&lt;br /&gt;
            ;&lt;br /&gt;
 }&lt;br /&gt;
 const title = &amp;quot;&amp;amp;lt;input type='button'&amp;amp;gt;&amp;quot;;&lt;br /&gt;
 const user = {firstName:'Hiroto', lastName:'Yagi', webpageUrl:'http://typea.info'};&lt;br /&gt;
 const element = (greeting(user,title)); &lt;br /&gt;
 [[React]]DOM.render(&lt;br /&gt;
     element,&lt;br /&gt;
     document.getElementById('root')&lt;br /&gt;
 );&lt;br /&gt;
[[File:1091_react06.jpg]]&lt;br /&gt;
====JSX [[R]]epresent オブジェクト====&lt;br /&gt;
*Babelは、[[React]].createElement()を呼び出しコンパイルを行う&lt;br /&gt;
*以下の2つは同じ意味&lt;br /&gt;
 const element1 = (&amp;amp;lt;h1 className='greeting'&amp;amp;gt;hello&amp;amp;lt;/h1&amp;amp;gt;);&lt;br /&gt;
 const element2 = [[React]].createElement('h1',{className:'greeting'},'hello');&lt;br /&gt;
*[[React]].createElement()は、バグを防ぐ手助けをするが、本質的には以下のようなオブジェクトを生成する&lt;br /&gt;
 // 簡易表現&lt;br /&gt;
 const element = {type:'h1',props:{className:'greeting',children:'hello'}};&lt;br /&gt;
*これらの要素を&amp;quot;[[React]] elements&amp;quot;と呼ぶ&lt;br /&gt;
*画面に表示させたいものの記述と考えることができる&lt;br /&gt;
*[[React]]はこれらのオブジェクトを読み、DOMの構築と最新化に利用する    &lt;br /&gt;
===Elementsのレンダリング===&lt;br /&gt;
*Elements は[[React]] アプリケーションの最小のビルディングブロック&lt;br /&gt;
*1つの要素は、画面上に表示するものを表現する&lt;br /&gt;
*ブラウザのDOM要素と異なり、[[React]] Elements はプレーンなオブジェクトで生成のコストは小さい&lt;br /&gt;
*[[React]] DOMは、DOMを[[React]] Elementsに一致するように取り扱う&lt;br /&gt;
====1つの要素を[[DOM]]の中にレンダリング====&lt;br /&gt;
*[[HTML]]どこかに記述する、以下のDIV要素をroot DOM ノードと呼ぶ&lt;br /&gt;
*[[React]] DOM が管理するすべてが、この要素の中にある&lt;br /&gt;
 &amp;amp;lt;div id=&amp;quot;root&amp;quot;&amp;amp;gt;&amp;amp;lt;/div&amp;amp;gt;&lt;br /&gt;
====[[React]]要素の更新====&lt;br /&gt;
*[[React]]要素は不変。一旦生成したら、子要素、属性などは変更できない。&lt;br /&gt;
*UIを更新するには、新しい要素を作成し、[[React]]DOM.rendar()に引き渡す。&lt;br /&gt;
 function tick() {&lt;br /&gt;
   const element = (&amp;amp;lt;div&amp;amp;gt;{(new Date()).toLocaleTimeString()}&amp;amp;lt;/div&amp;amp;gt;);&lt;br /&gt;
   [[React]]DOM.render(&lt;br /&gt;
       element,&lt;br /&gt;
       document.getElementById('root')&lt;br /&gt;
   );&lt;br /&gt;
 }&lt;br /&gt;
 setInterval(tick,1000);&lt;br /&gt;
[[File:1092_react07.jpg]]&lt;br /&gt;
&amp;amp;lt;blockquote&amp;amp;gt;通常の[[React]] アプリケーションでは、[[React]]DOM.rendar()は 一度しか呼びださない。&amp;amp;lt;/blockquote&amp;amp;gt;&lt;br /&gt;
====[[React]]は必要なもののみ更新する====&lt;br /&gt;
*[[React]] DOMは、要素および子要素を前の状態と比較し、DOMの更新が必要な個所にのみ適用する。&lt;br /&gt;
*ブラウザツールで、上記のソースコードを確認する&lt;br /&gt;
[[File:1093_react08.jpg]]&lt;br /&gt;
&amp;amp;lt;blockquote&amp;amp;gt;毎tick()の呼び出しで、すべてのUIツリーを生成するよう記述してるが、変更が発生したテキストノードのみ[[React]] DOMにより更新されている。&amp;amp;lt;/blockquote&amp;amp;gt;&lt;br /&gt;
===コンポーネントと Props===&lt;br /&gt;
*コンポーネントはUIを独立し再利用可能な部分に分割する。&lt;br /&gt;
*概念的にコンポーネントは[[JavaScript]]の関数のようなもの。&lt;br /&gt;
*コンポーネントはpropsと呼ばれる任意の入力を受け付け、[[React]] Elementを返す。&lt;br /&gt;
====コンポーネントの機能とクラス====&lt;br /&gt;
*[[JavaScript]]の関数としてコンポーネントを定義する&lt;br /&gt;
*この関数は有効な[[React]]コンポーネント、なぜなら、単一のprops引数を引数として取り、[[React]] Elementを返す。&lt;br /&gt;
*このようなコンポーネントを&amp;quot;functional&amp;quot;と呼ぶ。&lt;br /&gt;
 function Welcome(props) {&lt;br /&gt;
     return &amp;amp;lt;h1&amp;amp;gt;Hello,{props.name}&amp;amp;lt;/h1&amp;amp;gt;;&lt;br /&gt;
 }&lt;br /&gt;
*ES6のクラスをコンポーネントの定義として利用できる&lt;br /&gt;
 class Welcome extends [[React]].Component {&lt;br /&gt;
     render() {&lt;br /&gt;
         return &amp;amp;lt;h1&amp;amp;gt;Hello,{props.name}&amp;amp;lt;/h1&amp;amp;gt;;&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
*上記2つのコンポーネントは[[React]]の視点からは同じ&lt;br /&gt;
====コンポーネントのレンダリング====&lt;br /&gt;
*Elementは、ユーザー定義コンポーネントも表すことができる&lt;br /&gt;
 function Welcome(props) {&lt;br /&gt;
  return &amp;amp;lt;h1&amp;amp;gt;Hello,{props.name}&amp;amp;lt;/h1&amp;amp;gt;;&lt;br /&gt;
 }&lt;br /&gt;
 const element = &amp;amp;lt;Welcome name='Hiroto' /&amp;amp;gt;&lt;br /&gt;
 [[React]]DOM.render(&lt;br /&gt;
     element,&lt;br /&gt;
     document.getElementById('root')&lt;br /&gt;
 );&lt;br /&gt;
*[[React]]がユーザー定義コンポーネントを表示するときに、JSXの属性からコンポーネントへ&amp;quot;props&amp;quot;としてオブジェクトが渡される。&lt;br /&gt;
&lt;br /&gt;
&amp;amp;lt;blockquote&amp;amp;gt;コンポーネント名はいつも大文字から始める。[[DOM]] タグは、&amp;amp;lt;div /&amp;amp;gt; だが、&amp;amp;lt;Welcome /&amp;amp;gt; はコンポーネントを表現する。Welcomeがスコープに存在すること。&amp;amp;lt;/blockquote&amp;amp;gt;&lt;br /&gt;
====コンポーネントの構成====&lt;br /&gt;
*コンポーネントはその出力において、他のコンポーネントに影響を与えることができる&lt;br /&gt;
*同じコンポーネントをどんなレベルの詳細にも抽象的に利用できる、ボタン、フォーム、ダイアログ、スクリーン&lt;br /&gt;
*[[React]]でこれらは、一般にコンポーネントで表現される&lt;br /&gt;
 function Welcome(props) {&lt;br /&gt;
   return &amp;amp;lt;h1&amp;amp;gt;Hello,{props.name}&amp;amp;lt;/h1&amp;amp;gt;;&lt;br /&gt;
 }&lt;br /&gt;
 function App() {&lt;br /&gt;
   return ( &amp;amp;lt;div&amp;amp;gt;&lt;br /&gt;
       &amp;amp;lt;Welcome name=&amp;quot;Yagi&amp;quot;/&amp;amp;gt;&lt;br /&gt;
       &amp;amp;lt;Welcome name=&amp;quot;Kaela&amp;quot;/&amp;amp;gt;&lt;br /&gt;
       &amp;amp;lt;Welcome name=&amp;quot;Hiroto&amp;quot;/&amp;amp;gt;&lt;br /&gt;
     &amp;amp;lt;/div&amp;amp;gt; );&lt;br /&gt;
 }&lt;br /&gt;
 [[React]]DOM.render(&lt;br /&gt;
     &amp;amp;lt;App /&amp;amp;gt;,&lt;br /&gt;
     document.getElementById('root')&lt;br /&gt;
 );&lt;br /&gt;
*一般的に新しい[[React]]アプリケーションは、一つのAppコンポーネントを最上位に持つ。既存のアプリケーションに[[React]]を統合する場合は、小さなコンポーネント、例えばButtonなど、ボトムアップから開始し、徐々にView階層の最上位にいたる。&lt;br /&gt;
&lt;br /&gt;
&amp;amp;lt;blockquote&amp;amp;gt;コンポーネントは、一つのroot要素を返さなければならない。上記で、Welcome要素を div に含めたのはこのため&amp;amp;lt;/blockquote&amp;amp;gt;&lt;br /&gt;
====Propsは読み取り専用====&lt;br /&gt;
**[[React]]はかなりフレキシブルだが、1つ厳格なルールがある。function だろうと class だろうとコンポーネントはpropsを編集できない。&lt;br /&gt;
===状態とライフサイクル===&lt;br /&gt;
*次のClockコンポーネントを再利用可能にカプセル化する&lt;br /&gt;
 function Clock(props) {&lt;br /&gt;
   return (&lt;br /&gt;
     &amp;amp;lt;div&amp;amp;gt;&lt;br /&gt;
       &amp;amp;lt;h2&amp;amp;gt;{props.date.toLocaleTimeString()}&amp;amp;lt;/h2&amp;amp;gt;&lt;br /&gt;
     &amp;amp;lt;/div&amp;amp;gt;&lt;br /&gt;
   );&lt;br /&gt;
 }&lt;br /&gt;
 function tick() {&lt;br /&gt;
   [[React]]DOM.render(&lt;br /&gt;
       &amp;amp;lt;Clock date={new Date()} /&amp;amp;gt;,&lt;br /&gt;
       document.getElementById('root')&lt;br /&gt;
   );&lt;br /&gt;
 }&lt;br /&gt;
 setInterval(tick, 1000);&lt;br /&gt;
&lt;br /&gt;
[[File:1094_react09.jpg]]&lt;br /&gt;
&lt;br /&gt;
*実装のために、Clockコンポーネントにstateを追加する。&lt;br /&gt;
*状態は、propsと同様だが、private かつ、コンポーネントから完全に制御される&lt;br /&gt;
*クラス宣言したコンポーネントにはいくつかの追加的な機能があるが、local state はこれにあたる&lt;br /&gt;
====関数をクラスに変更する====&lt;br /&gt;
#[[React]].Component を継承して同名のES6クラスを作成する&lt;br /&gt;
#render()メソッドを作成し、処理を移動、functionを削除&lt;br /&gt;
#propsをthis.propsに変更&lt;br /&gt;
 class Clock extends [[React]].Component {&lt;br /&gt;
   render() {&lt;br /&gt;
     return (&lt;br /&gt;
       &amp;amp;lt;div&amp;amp;gt;&lt;br /&gt;
         &amp;amp;lt;h2&amp;amp;gt;{this.props.date.toLocaleTimeString()}&amp;amp;lt;/h2&amp;amp;gt;&lt;br /&gt;
       &amp;amp;lt;/div&amp;amp;gt;&lt;br /&gt;
     );&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
====クラスにローカル状態を追加する====&lt;br /&gt;
*date を props から state へ移動する&lt;br /&gt;
#render()メソッドの中の、this.props.date を this.state.date に変更&lt;br /&gt;
#クラスにコンストラクタを追加し、this.stateの初期状態を記述する&lt;br /&gt;
#&amp;amp;lt;Clock date={new Date()} /&amp;amp;gt; から dateを削除&lt;br /&gt;
 class Clock extends [[React]].Component {&lt;br /&gt;
   constructor(props) {&lt;br /&gt;
     super(props);&lt;br /&gt;
     this.state = {date : new Date()};&lt;br /&gt;
   }&lt;br /&gt;
   render() {&lt;br /&gt;
     return (&lt;br /&gt;
       &amp;amp;lt;div&amp;amp;gt;&lt;br /&gt;
         &amp;amp;lt;h2&amp;amp;gt;{this.state.date.toLocaleTimeString()}&amp;amp;lt;/h2&amp;amp;gt;&lt;br /&gt;
       &amp;amp;lt;/div&amp;amp;gt;&lt;br /&gt;
     );&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
====クラスにライフサイクルメソッドを追加する====&lt;br /&gt;
*多くのコンポーネントを使用するアプリケーションでは、破棄されたコンポーネントのリソースの解放が重要&lt;br /&gt;
*ClockがDOMに最初にレンダリングされるときには、必ずタイマーをセットアップしたい。これを[[React]]では、&amp;quot;mounting&amp;quot; という&lt;br /&gt;
*また、ClockがDOMから取り除かれるときには、タイマーをクリアしたい。これを[[React]]では、&amp;quot;unmounting&amp;quot;という&lt;br /&gt;
*コンポーネントが、mount/unmount されるときに実行される特別なメソッドをクラスに宣言できる&lt;br /&gt;
*componentDidMount()、componentWillUnmount() これらのメソッドはライフサイクルフックと呼ばれる&lt;br /&gt;
*どのようにtimer IDを thisに保存するか&lt;br /&gt;
**this.propsが[[React]]によりセットアップされる間、this.stateは特別な意味を持つ&lt;br /&gt;
**表示に使用しないならば、クラスに自由にフィールドを追加できる&lt;br /&gt;
**render()の中では、それらは利用できないし、ステートも持たない&lt;br /&gt;
*最後に、毎秒実行されるtick()メソッドを実装する。&lt;br /&gt;
*this.setState()でローカルコンポーネントの状態を更新する&lt;br /&gt;
&lt;br /&gt;
 class Clock extends [[React]].Component {&lt;br /&gt;
   constructor(props) {&lt;br /&gt;
     super(props);&lt;br /&gt;
     this.state = {date : new Date()};&lt;br /&gt;
   }&lt;br /&gt;
   componentDidMount() {&lt;br /&gt;
     this.timerID = setInterval(&lt;br /&gt;
       () =&amp;amp;gt; this.tick(),1000&lt;br /&gt;
     );&lt;br /&gt;
   }&lt;br /&gt;
   componentWillUnmount() {&lt;br /&gt;
     clearInterval(this.timerID);&lt;br /&gt;
   }&lt;br /&gt;
   tick() {&lt;br /&gt;
     this.setState({&lt;br /&gt;
       date: new Date()&lt;br /&gt;
     });&lt;br /&gt;
   }&lt;br /&gt;
   render() {&lt;br /&gt;
     return (&lt;br /&gt;
       &amp;amp;lt;div&amp;amp;gt;&lt;br /&gt;
         &amp;amp;lt;h2&amp;amp;gt;{this.state.date.toLocaleTimeString()}&amp;amp;lt;/h2&amp;amp;gt;&lt;br /&gt;
       &amp;amp;lt;/div&amp;amp;gt;&lt;br /&gt;
     );&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
 [[React]]DOM.render(&lt;br /&gt;
   &amp;amp;lt;Clock /&amp;amp;gt;,&lt;br /&gt;
   document.getElementById('root')&lt;br /&gt;
 );&lt;br /&gt;
====状態を正しく使う====&lt;br /&gt;
=====stateを直接操作しない=====&lt;br /&gt;
 // まちがい&lt;br /&gt;
 this.state.comment = 'Hello';&lt;br /&gt;
*上記の代わりに、setState() を利用する&lt;br /&gt;
 // 正しい&lt;br /&gt;
 this.setSatate({comment:'Hello'});&lt;br /&gt;
&amp;amp;lt;blockquote&amp;amp;gt;this.stateを割り当てることができるのは、コンストラクタのみ&amp;amp;lt;/blockquote&amp;amp;gt;&lt;br /&gt;
=====stateは、非同期に更新される=====&lt;br /&gt;
*[[React]]は、複数のsetState() をパフォーマンスのためにまとめて一度に処理する。&lt;br /&gt;
*このため、this.propsとthis.stateは非同期に更新される&lt;br /&gt;
*これらの値を信頼して、次の状態への計算を行うべきではない&lt;br /&gt;
 // まちがい&lt;br /&gt;
 this.setState({&lt;br /&gt;
   counter: this.state.counter + this.props.increament,&lt;br /&gt;
 });&lt;br /&gt;
*修正するには、オブジェクトではなく関数を受け取る、setState()を使用する&lt;br /&gt;
*関数は、ひとつ前の状態(state)を最初の引数として、更新時のpropsを2つ目の引数として取る&lt;br /&gt;
 // 正しい&lt;br /&gt;
 this.setState((prevState, props) =&amp;amp;gt; ({&lt;br /&gt;
   counter: prevState.counter + prpos.increament&lt;br /&gt;
 }));&lt;br /&gt;
*通常の関数でもよい&lt;br /&gt;
 // 正しい&lt;br /&gt;
 this.setState(function(prevState, props) {&lt;br /&gt;
   return { counter: prevState.counter + props.increament };&lt;br /&gt;
 });&lt;br /&gt;
=====状態の更新はマージされる=====&lt;br /&gt;
*setState()を呼び出すと、[[React]]は、現在のstateに提供したオブジェクトをマージする&lt;br /&gt;
*例えば、いくつかの独立した変数を含む場合&lt;br /&gt;
 constructor(props) {&lt;br /&gt;
   super(props);&lt;br /&gt;
   this.state = {&lt;br /&gt;
     posts: []&lt;br /&gt;
     comments: []&lt;br /&gt;
   };&lt;br /&gt;
 }&lt;br /&gt;
*これらを別のsetState() で更新&lt;br /&gt;
 componentDidMount() {&lt;br /&gt;
   fetchPosts().then(response =&amp;amp;gt; { this.setState({ posts: response.posts }); });&lt;br /&gt;
   fetchComments().then(response =&amp;amp;gt; { this.setState({ commentss: response.comments }); });&lt;br /&gt;
 }&lt;br /&gt;
*マージはシャローなので、setState({comment}) は、this.state.posts を損なわずに、this.state.comments を置き換える&lt;br /&gt;
====データは下へ流れる====&lt;br /&gt;
*親だけでなく子コンポーネントも確実にステートフルかステートレスか知ることはできない。&lt;br /&gt;
*状態はしばしばローカルから呼び出されるかカプセル化されていて、他からアクセスできない。&lt;br /&gt;
*コンポーネントは、自身の状態をpropsを通して子コンポーネントに渡す&lt;br /&gt;
 &amp;amp;lt;h2&amp;amp;gt;It is {this.state.date.toLocalTimeString()}.&amp;amp;lt;/h2&amp;amp;gt;&lt;br /&gt;
*これは、ユーザー定義コンポーネントでも動作する&lt;br /&gt;
&amp;amp;lt;FormattedDate date={this.state.date} /&amp;amp;gt;&lt;br /&gt;
*FormattedDateコンポーネントは、propsにdateを受け取り、Clockの状態が何かは知らない。&lt;br /&gt;
 function FormatterDate(props) {&lt;br /&gt;
   return &amp;amp;lt;h2&amp;amp;gt;It is {props.date.toLocaleTimeString()}.&amp;amp;lt;/h2&amp;amp;gt;;&lt;br /&gt;
 }&lt;br /&gt;
*これは一般的に、トップダウン、もしくは、ユニディレクショナル データフローという&lt;br /&gt;
*状態は常に特定のコンポーネントに属する。&lt;br /&gt;
*データやUIは状態に由来し、ツリーのより下のコンポーネントにのみ影響を与えることができる&lt;br /&gt;
===イベントの処理===&lt;br /&gt;
*[[React]] 要素のイベント処理は、DOMでの処理ととても似ているが、いくつかシンタックスの差異がある。&lt;br /&gt;
**[[React]]イベントは、ロウアーケースではなく、キャメルケース&lt;br /&gt;
**JSXでは、stringではなく、関数をイベントハンドラーとして渡す。&lt;br /&gt;
&lt;br /&gt;
=====[[HTML]]=====&lt;br /&gt;
 &amp;amp;lt;button onclick=&amp;quot;test()&amp;quot; /&amp;amp;gt;&lt;br /&gt;
=====[[React]]=====&lt;br /&gt;
 &amp;amp;lt;button onClick={test} /&amp;amp;gt;&lt;br /&gt;
&lt;br /&gt;
*もう一つの違いは、[[React]]では、falseを返しデフォルトのふるまいを防止することができない。&lt;br /&gt;
*明示的に、preventDefault を呼び出す必要がある。&lt;br /&gt;
&lt;br /&gt;
=====[[HTML]]でデフォルトの新しいページを開くリンクのふるまいを防止する=====&lt;br /&gt;
 &amp;amp;lt;a href=&amp;quot;#&amp;quot; onclick=&amp;quot;console.log('hoge'); return false&amp;quot; &amp;amp;gt;Click&amp;amp;lt;/a&amp;amp;gt;&lt;br /&gt;
=====[[React]]=====&lt;br /&gt;
 function ActionLink() {&lt;br /&gt;
   function handleClick(e) {&lt;br /&gt;
     e.preventDefault();&lt;br /&gt;
     console.log('hoge');&lt;br /&gt;
   }&lt;br /&gt;
   return (&lt;br /&gt;
     &amp;amp;lt;a href=&amp;quot;#&amp;quot; onClick={handleClick} &amp;amp;gt;Click&amp;amp;lt;/a&amp;amp;gt;&lt;br /&gt;
   )&lt;br /&gt;
 } &lt;br /&gt;
*e は、本物ではないイベント。Reactでは、[https://www.w3.org/TR/DOM-Level-3-Events/ W3C]に合わせるために定義している。&lt;br /&gt;
*なので、ブラウザの互換性を心配する必要はない。[https://facebook.github.io/react/docs/events.html リファレンス]を参照&lt;br /&gt;
*[[React]]では、addEventListenerを通常呼び出す必要はない。要素が最初にレンダリングされるときに提供される&lt;br /&gt;
*ES6のクラスを使用するときの一般的なパターン、例えば、Toggle ボタン&lt;br /&gt;
 class Toggle extends [[React]].Component {&lt;br /&gt;
   constructor(props) {&lt;br /&gt;
     super(props);&lt;br /&gt;
     this.state = {isToggleOn: true};&lt;br /&gt;
     this.handleClick = this.handleClick.bind(this);&lt;br /&gt;
   }&lt;br /&gt;
   handleClick() {&lt;br /&gt;
     this.setState(prevStae =&amp;amp;gt; ({&lt;br /&gt;
       isToggleOn: !prevStae.isToggleOn&lt;br /&gt;
     }));&lt;br /&gt;
   }&lt;br /&gt;
   render() {&lt;br /&gt;
     return (&lt;br /&gt;
       &amp;amp;lt;button onClick={this.handleClick} &amp;amp;gt;&lt;br /&gt;
         {this.state.isToggleOn?&amp;quot;ON&amp;quot;:&amp;quot;OFF&amp;quot;}&lt;br /&gt;
       &amp;amp;lt;/button&amp;amp;gt;&lt;br /&gt;
     );&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
 [[React]]DOM.render(&lt;br /&gt;
   &amp;amp;lt;Toggle /&amp;amp;gt;,&lt;br /&gt;
   document.getElementById('root')&lt;br /&gt;
 );&lt;br /&gt;
*この文法の問題点は、LoggingButtonがレンダリングされるたびに、異なったコールバックが生成されること&lt;br /&gt;
*多くのケースで、これは問題ないが、このコールバックが下位のコンポーネントにpropとして渡される場合、コンポーネントは余分にレンダリングすることになる。&lt;br /&gt;
*コンストラクタでバインドするか、プロパティイニシャライザでバインドすることを推奨する。&lt;br /&gt;
===条件付きのレンダリング===&lt;br /&gt;
*[[React]]では、必要なら、振る舞いがカプセルかされた他と異なったコンポーネントを作成できる。&lt;br /&gt;
*Reactの条件付きレンダリングは、[[JavaScript]]の条件が動作するのと同じ方法で動作する。&lt;br /&gt;
*[[JavaScript]]のifのような演算子もしくは、条件演算子は、現在の状態を表した要素を作成するための、ReactがUIをそれに一致させることを許す。&lt;br /&gt;
=====以下の2つのコンポーネントについて考える=====&lt;br /&gt;
*ユーザーがログインしているか否かによって使い分けたい。&lt;br /&gt;
*isLoggedIn により、異なるレンダリングがなされる。&lt;br /&gt;
 function UserGreeting(props){&lt;br /&gt;
    return &amp;amp;lt;h1&amp;amp;gt;Welcome to back!&amp;amp;lt;/h1&amp;amp;gt;&lt;br /&gt;
 }    &lt;br /&gt;
 function GuestGreeting(props) {&lt;br /&gt;
    return &amp;amp;lt;h1&amp;amp;gt;Please Sign up!&amp;amp;lt;/h1&amp;amp;gt;&lt;br /&gt;
 }&lt;br /&gt;
 function Greeting(props) {&lt;br /&gt;
    const isLoggedIn = props.isLoggedIn;&lt;br /&gt;
    if (isLoggedIn) {&lt;br /&gt;
      return &amp;amp;lt;UserGreeting /&amp;amp;gt;&lt;br /&gt;
    } else {&lt;br /&gt;
      return &amp;amp;lt;GuestGreeting /&amp;amp;gt;&lt;br /&gt;
    }&lt;br /&gt;
 }    &lt;br /&gt;
 [[React]]DOM.render(&lt;br /&gt;
   &amp;amp;lt;Greeting isLoggedIn={true} /&amp;amp;gt;,&lt;br /&gt;
   document.getElementById('root')&lt;br /&gt;
 );&lt;br /&gt;
====要素変数====&lt;br /&gt;
*要素を保持するのに変数を利用できる。&lt;br /&gt;
*これは、出力結果が変わらない間に、条件によりコンポーネントの一部をレンダリングするのを助ける。&lt;br /&gt;
 function LoginButton(props) {&lt;br /&gt;
    return (&lt;br /&gt;
      &amp;amp;lt;button onClick={props.onClick} &amp;amp;gt;&lt;br /&gt;
        Login      &lt;br /&gt;
      &amp;amp;lt;/button&amp;amp;gt;&lt;br /&gt;
    );&lt;br /&gt;
 }&lt;br /&gt;
 function LogoutButton(props) {&lt;br /&gt;
    return (&lt;br /&gt;
      &amp;amp;lt;button onClick={props.onClick} &amp;amp;gt;&lt;br /&gt;
        Logout      &lt;br /&gt;
      &amp;amp;lt;/button&amp;amp;gt;&lt;br /&gt;
    );&lt;br /&gt;
 }&lt;br /&gt;
 class LoginControl extends [[React]].Component {&lt;br /&gt;
    constructor(props) {&lt;br /&gt;
      super(props);&lt;br /&gt;
      this.handleLoginClick = this.handleLoginClick.bind(this);&lt;br /&gt;
      this.handleLogoutClick = this.handleLogoutClick.bind(this);&lt;br /&gt;
      this.state = {isLoggedIn: false};&lt;br /&gt;
    }&lt;br /&gt;
    handleLoginClick() {&lt;br /&gt;
      this.setState({isLoggedIn: true});&lt;br /&gt;
    }&lt;br /&gt;
    handleLogoutClick(){&lt;br /&gt;
      this.setState({isLoggedIn: false});&lt;br /&gt;
    }&lt;br /&gt;
    render() {&lt;br /&gt;
      const isLoggedIn = this.state.isLoggedIn;&lt;br /&gt;
      let button = null;&lt;br /&gt;
      if (isLoggedIn) {&lt;br /&gt;
        button = &amp;amp;lt;LogoutButton onClick={this.handleLogoutClick} /&amp;amp;gt;&lt;br /&gt;
      } else {&lt;br /&gt;
        button = &amp;amp;lt;LoginButton onClick={this.handleLoginClick} /&amp;amp;gt;&lt;br /&gt;
      }&lt;br /&gt;
      return (&amp;amp;lt;div&amp;amp;gt;{button}&amp;amp;lt;/div&amp;amp;gt;);&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 [[React]]DOM.render(&lt;br /&gt;
   &amp;amp;lt;LoginControl /&amp;amp;gt;,&lt;br /&gt;
   document.getElementById('root')&lt;br /&gt;
 );&lt;br /&gt;
[[File:1085_react_debug.jpg]]&lt;br /&gt;
====インラインif と 論理 &amp;amp;&amp;amp; 演算子====&lt;br /&gt;
*true &amp;amp;&amp;amp; 演算子の場合評価され、false &amp;amp;&amp;amp; の場合、falseとなり[[React]]は無視する&lt;br /&gt;
 function MailBox(props) {&lt;br /&gt;
    const unreadMessages = props.unreadMessages;&lt;br /&gt;
    return  (&lt;br /&gt;
      &amp;amp;lt;div&amp;amp;gt;&lt;br /&gt;
        &amp;amp;lt;h1&amp;amp;gt;Hello!&amp;amp;lt;/h1&amp;amp;gt;&lt;br /&gt;
        {unreadMessages.length &amp;amp;gt; 0 &amp;amp;&amp;amp;&lt;br /&gt;
          &amp;amp;lt;h2&amp;amp;gt;&lt;br /&gt;
            You have {unreadMessages.length} unread messages.&lt;br /&gt;
          &amp;amp;lt;/h2&amp;amp;gt;&lt;br /&gt;
        }&lt;br /&gt;
      &amp;amp;lt;/div&amp;amp;gt;&lt;br /&gt;
    );&lt;br /&gt;
 }&lt;br /&gt;
 const messages = ['message1','message2'];&lt;br /&gt;
 [[React]]DOM.render(&lt;br /&gt;
   &amp;amp;lt;MailBox unreadMessages={messages} /&amp;amp;gt;,&lt;br /&gt;
   document.getElementById('root')&lt;br /&gt;
 );&lt;br /&gt;
====インライン if-else とコンディション演算子====&lt;br /&gt;
*条件 ? true : false&lt;br /&gt;
 function UserGreeting(props){&lt;br /&gt;
     return &amp;amp;lt;h1&amp;amp;gt;Welcome to back!&amp;amp;lt;/h1&amp;amp;gt;&lt;br /&gt;
 }    &lt;br /&gt;
 function GuestGreeting(props) {&lt;br /&gt;
     return &amp;amp;lt;h1&amp;amp;gt;Please Sign up!&amp;amp;lt;/h1&amp;amp;gt;&lt;br /&gt;
 }&lt;br /&gt;
 function Greeting(props) {&lt;br /&gt;
     const isLoggedIn = props.isLoggedIn;&lt;br /&gt;
     return (&lt;br /&gt;
       &amp;amp;lt;div&amp;amp;gt;&lt;br /&gt;
       {isLoggedIn ? (&lt;br /&gt;
           &amp;amp;lt;UserGreeting /&amp;amp;gt;&lt;br /&gt;
         ) : (&lt;br /&gt;
           &amp;amp;lt;GuestGreeting /&amp;amp;gt;&lt;br /&gt;
         )&lt;br /&gt;
       }&lt;br /&gt;
       &amp;amp;lt;/div&amp;amp;gt;&lt;br /&gt;
     );&lt;br /&gt;
 }    &lt;br /&gt;
 [[React]]DOM.render(&lt;br /&gt;
   &amp;amp;lt;Greeting isLoggedIn={false} /&amp;amp;gt;,&lt;br /&gt;
   document.getElementById('root')&lt;br /&gt;
 );&lt;br /&gt;
====コンポーネントのレンダリングさせない====&lt;br /&gt;
*他のコンポーネントからレンダリングされたとしてもコンポーネントを隠したい場合、render出力の代わりにnullを返す&lt;br /&gt;
 function WarningBanner(props){&lt;br /&gt;
   if(!props.warn) {&lt;br /&gt;
     return null;&lt;br /&gt;
   }&lt;br /&gt;
   return (&lt;br /&gt;
     &amp;amp;lt;div&amp;amp;gt;Warning!&amp;amp;lt;/div&amp;amp;gt;&lt;br /&gt;
   );&lt;br /&gt;
 }&lt;br /&gt;
 class Page extends [[React]].Component {&lt;br /&gt;
   constructor(props) {&lt;br /&gt;
     super(props);&lt;br /&gt;
     this.state = {showWarning : true}&lt;br /&gt;
     this.handleToggleClick = this.handleToggleClick.bind(this);&lt;br /&gt;
   }&lt;br /&gt;
   handleToggleClick() {&lt;br /&gt;
     this.setState(prevState =&amp;amp;gt;({showWarning : !prevState.showWarning}));&lt;br /&gt;
   }&lt;br /&gt;
   render() {&lt;br /&gt;
     return (&lt;br /&gt;
       &amp;amp;lt;div&amp;amp;gt;&lt;br /&gt;
         &amp;amp;lt;WarningBanner warn={this.state.showWarning} /&amp;amp;gt;&lt;br /&gt;
         &amp;amp;lt;button onClick={this.handleToggleClick}&amp;amp;gt;&lt;br /&gt;
           {this.state.showWarning ? 'Hide' : 'Show'}&lt;br /&gt;
         &amp;amp;lt;/button&amp;amp;gt;&lt;br /&gt;
       &amp;amp;lt;/div&amp;amp;gt;&lt;br /&gt;
     );&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 [[React]]DOM.render(&lt;br /&gt;
   &amp;amp;lt;Page /&amp;amp;gt;,&lt;br /&gt;
   document.getElementById('root')&lt;br /&gt;
 );&lt;br /&gt;
[[File:1095_react10.jpg]]&lt;br /&gt;
===リストとキー===&lt;br /&gt;
=====[[JavaScript]]でリストの変換には、map()を利用する=====&lt;br /&gt;
 const numbers = [1,2,3,4,5];&lt;br /&gt;
 const doubled = numbers.map((number)=&amp;amp;gt; number * 2);&lt;br /&gt;
 console.log(doubled)&lt;br /&gt;
 &amp;amp;gt; [2, 4, 6, 8, 10]&lt;br /&gt;
*[[React]] では同様に配列をリストに変換する&lt;br /&gt;
====複数のコンポーネントをレンダリングする====&lt;br /&gt;
 const fruits = ['apple','orange','grape','banana'];&lt;br /&gt;
 const listItems = fruits.map((fruit) =&amp;amp;gt; &amp;amp;lt;li&amp;amp;gt;{fruit}&amp;amp;lt;/li&amp;amp;gt;);&lt;br /&gt;
 [[React]]DOM.render(&lt;br /&gt;
   &amp;amp;lt;ol&amp;amp;gt;{listItems}&amp;amp;lt;/ol&amp;amp;gt;,&lt;br /&gt;
   document.getElementById('root')&lt;br /&gt;
 );&lt;br /&gt;
&lt;br /&gt;
[[File:1096_react11.jpg]]&lt;br /&gt;
====基本的なリストコンポーネント====&lt;br /&gt;
*通常リストはコンポーネントに含まれる&lt;br /&gt;
=====Keys=====&lt;br /&gt;
*keyを指定しないと警告がでる&lt;br /&gt;
*keyは、[[React]]が、どのアイテムが登録、変更、削除されたのか特定するのに役立つ&lt;br /&gt;
*文字列で兄弟間でユニークな値を設定するのが望ましい&lt;br /&gt;
 function FruitList(props) {&lt;br /&gt;
   const fruits = props.fruits;&lt;br /&gt;
   const listItems = fruits.map((fruit) =&amp;amp;gt; &amp;amp;lt;li key={fruit}&amp;amp;gt;{fruit}&amp;amp;lt;/li&amp;amp;gt;);&lt;br /&gt;
   return (&lt;br /&gt;
     &amp;amp;lt;ol&amp;amp;gt;{listItems}&amp;amp;lt;/ol&amp;amp;gt; &lt;br /&gt;
   );&lt;br /&gt;
 } &lt;br /&gt;
 const fruits = ['apple','orange','grape','banana'];&lt;br /&gt;
 [[React]]DOM.render(&lt;br /&gt;
   &amp;amp;lt;FruitList fruits={fruits}/&amp;amp;gt;,&lt;br /&gt;
   document.getElementById('root')&lt;br /&gt;
 );&lt;br /&gt;
====コンポーネントをKeyと取り出す====&lt;br /&gt;
*Keyが意味を持つのは、配列を囲むコンテキストにおいて&lt;br /&gt;
*兄弟間で同じKeyを持つとエラーとなる&lt;br /&gt;
 function ListItem(props) {&lt;br /&gt;
   // この&amp;amp;lt;li&amp;amp;gt; にKeyを設定するのは、ここがルートになるため間違い&lt;br /&gt;
   return &amp;amp;lt;li&amp;amp;gt;{props.value}&amp;amp;lt;/li&amp;amp;gt;&lt;br /&gt;
 }&lt;br /&gt;
 function FruitList(props) {&lt;br /&gt;
   const fruits = props.fruits;&lt;br /&gt;
   // &amp;amp;lt;ListItem&amp;amp;gt;の配列となるため、ここでKeyを指定するのが正しい&lt;br /&gt;
   const listItems = fruits.map((fruit) =&amp;amp;gt; &amp;amp;lt;ListItem key={fruit} value={fruit} /&amp;amp;gt;);&lt;br /&gt;
   return (&lt;br /&gt;
     &amp;amp;lt;ol&amp;amp;gt;{listItems}&amp;amp;lt;/ol&amp;amp;gt; &lt;br /&gt;
   );&lt;br /&gt;
 } &lt;br /&gt;
 const fruits = ['apple','orange','grape','banana'];&lt;br /&gt;
 [[React]]DOM.render(&lt;br /&gt;
   &amp;amp;lt;FruitList fruits={fruits}/&amp;amp;gt;,&lt;br /&gt;
   document.getElementById('root')&lt;br /&gt;
 );&lt;br /&gt;
====JSXでmap()を埋め込む====&lt;br /&gt;
*中括弧のインラインにmap()を置くことができる&lt;br /&gt;
 function ListItem(props) {&lt;br /&gt;
   return &amp;amp;lt;li&amp;amp;gt;{props.value}&amp;amp;lt;/li&amp;amp;gt;&lt;br /&gt;
 }&lt;br /&gt;
 function FruitList(props) {&lt;br /&gt;
   const fruits = props.fruits;&lt;br /&gt;
   return (&lt;br /&gt;
     &amp;amp;lt;ol&amp;amp;gt;{fruits.map((fruit) =&amp;amp;gt; &amp;amp;lt;ListItem key={fruit} value={fruit} /&amp;amp;gt;)}&amp;amp;lt;/ol&amp;amp;gt; &lt;br /&gt;
   );&lt;br /&gt;
&lt;br /&gt;
 } &lt;br /&gt;
 const fruits = ['apple','orange','grape','banana'];&lt;br /&gt;
 [[React]]DOM.render(&lt;br /&gt;
   &amp;amp;lt;FruitList fruits={fruits}/&amp;amp;gt;,&lt;br /&gt;
   document.getElementById('root')&lt;br /&gt;
 );&lt;br /&gt;
===Form===&lt;br /&gt;
*HTML Formは、[[React]]では、少し他のDOMとは動作が異なる。&lt;br /&gt;
*なぜなら Fromは通常内部状態をもつから。&lt;br /&gt;
====コントロールされたコンポーネント====&lt;br /&gt;
*[[HTML]]でFormは、自身の状態を維持しユーザー入力に基づいて状態を更新する。&lt;br /&gt;
*[[React]]では、変化可能な状態はコンポーネントのstateプロパティに保持し、setState()からのみ更新される。&lt;br /&gt;
*&amp;quot;single source of truth&amp;quot;として[[React]] stateを作成することにより2つを結びつけることができる。&lt;br /&gt;
*[[React]]コンポーネントはFormまたコントロールでユーザー入力により、何が起きたかを描画する。&lt;br /&gt;
*input Form 要素の値は、[[React]]によりこの方法で制御される。&lt;br /&gt;
*これは、「コントロールされたコンポーネント」と呼ばれる。&lt;br /&gt;
&lt;br /&gt;
 class NameForm extends [[React]].Component {&lt;br /&gt;
   constructor(props) {&lt;br /&gt;
     super(props);&lt;br /&gt;
     this.state = {value : ''};&lt;br /&gt;
     this.handleChange = this.handleChange.bind(this);&lt;br /&gt;
     this.handleSubmit = this.handleSubmit.bind(this);&lt;br /&gt;
   }&lt;br /&gt;
   handleChange(event) {&lt;br /&gt;
     this.setState({value : event.target.value });&lt;br /&gt;
   }&lt;br /&gt;
   handleSubmit(event) {&lt;br /&gt;
     alert('A name was submitted ' + this.state.value);&lt;br /&gt;
     event.preventDefault();&lt;br /&gt;
   }&lt;br /&gt;
   render() {&lt;br /&gt;
     return(&lt;br /&gt;
       &amp;amp;lt;form onSubmit={this.handleSubmit}&amp;amp;gt;&lt;br /&gt;
          &amp;amp;lt;label&amp;amp;gt;Name: &amp;amp;lt;input type=&amp;quot;text&amp;quot; value={this.state.value} onChange={this.handleChange} /&amp;amp;gt;&amp;amp;lt;/label&amp;amp;gt;&lt;br /&gt;
          &amp;amp;lt;input type=&amp;quot;submit&amp;quot; value=&amp;quot;Submit&amp;quot;/&amp;amp;gt;&lt;br /&gt;
       &amp;amp;lt;/form&amp;amp;gt;&lt;br /&gt;
     );&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
 [[React]]DOM.render(&lt;br /&gt;
   &amp;amp;lt;NameForm /&amp;amp;gt;,&lt;br /&gt;
   document.getElementById('root')&lt;br /&gt;
 );&lt;br /&gt;
[[File:1097_react12.jpg]]&lt;br /&gt;
*valueが、Form要素に設定されると、表示されるvalueは、常にthis.state.valueとなる&lt;br /&gt;
*すべてのキーストロークで、handleChangeが起動し、[[React]]のstateを更新する&lt;br /&gt;
*表示されるvalueも更新される&lt;br /&gt;
 handleChange(event) {&lt;br /&gt;
   this.setState({value : event.target.value.toUpperCase() });&lt;br /&gt;
 }&lt;br /&gt;
====textarea/select タグ====&lt;br /&gt;
 class SelectParts extends [[React]].Component {&lt;br /&gt;
   constructor(props){&lt;br /&gt;
     super(props);&lt;br /&gt;
     this.state = {value: 'coconuts'};&lt;br /&gt;
     this.handleChange = this.handleChange.bind(this);&lt;br /&gt;
   }&lt;br /&gt;
   handleChange(event) {&lt;br /&gt;
     this.setState({value: event.target.value});&lt;br /&gt;
   }&lt;br /&gt;
   render(){&lt;br /&gt;
     return(&lt;br /&gt;
       &amp;amp;lt;label&amp;amp;gt;Select:&lt;br /&gt;
         &amp;amp;lt;select value={this.state.value} onChange={this.handleChange}&amp;amp;gt;&lt;br /&gt;
           &amp;amp;lt;option value=&amp;quot;grapefruit&amp;quot;&amp;amp;gt;Grape Fruit&amp;amp;lt;/option&amp;amp;gt;&lt;br /&gt;
           &amp;amp;lt;option value=&amp;quot;lime&amp;quot;&amp;amp;gt;Lime&amp;amp;lt;/option&amp;amp;gt;&lt;br /&gt;
           &amp;amp;lt;option value=&amp;quot;coconuts&amp;quot;&amp;amp;gt;Coconuts&amp;amp;lt;/option&amp;amp;gt;&lt;br /&gt;
           &amp;amp;lt;option value=&amp;quot;mango&amp;quot;&amp;amp;gt;Mango&amp;amp;lt;/option&amp;amp;gt;&lt;br /&gt;
         &amp;amp;lt;/select&amp;amp;gt;&lt;br /&gt;
       &amp;amp;lt;/label&amp;amp;gt;&lt;br /&gt;
     );&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
 class TextareaParts extends [[React]].Component {&lt;br /&gt;
   constructor(props){&lt;br /&gt;
     super(props);&lt;br /&gt;
     this.state = {&lt;br /&gt;
       value : 'なにか書いて'&lt;br /&gt;
     };&lt;br /&gt;
     this.handleChange = this.handleChange.bind(this);&lt;br /&gt;
   }&lt;br /&gt;
   handleChange(event) {&lt;br /&gt;
     this.setState({value : event.target.value});&lt;br /&gt;
   }&lt;br /&gt;
   render(){&lt;br /&gt;
     return (&lt;br /&gt;
         &amp;amp;lt;label&amp;amp;gt;Textarea:&amp;amp;lt;textarea value={this.state.value} onChange={this.handleChange} /&amp;amp;gt;&amp;amp;lt;/label&amp;amp;gt;&lt;br /&gt;
     );&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
 [[React]]DOM.render(&lt;br /&gt;
   &amp;amp;lt;div&amp;amp;gt;&lt;br /&gt;
     &amp;amp;lt;SelectParts /&amp;amp;gt;&lt;br /&gt;
     &amp;amp;lt;TextareaParts /&amp;amp;gt;&lt;br /&gt;
   &amp;amp;lt;/div&amp;amp;gt;,&lt;br /&gt;
   document.getElementById('root')&lt;br /&gt;
 );&lt;br /&gt;
====複数入力項目の処理====&lt;br /&gt;
*複数のコントロールされた入力要素を処理したい場合、name属性を各要素に追加する&lt;br /&gt;
*ハンドラー関数で、event.target.name の値に基づいて、どの要素か判定&lt;br /&gt;
*ES6 [https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Operators/Object_initializer#Computed_property_names 計算されたプロパティ名]構文をkey状態を更新するのに使用&lt;br /&gt;
 class Reservation extends [[React]].Component {&lt;br /&gt;
   constructor(props) {&lt;br /&gt;
     super(props);&lt;br /&gt;
     this.state = {&lt;br /&gt;
       isGoing: true,&lt;br /&gt;
       numberOfGuests: 2&lt;br /&gt;
     };&lt;br /&gt;
     this.handleInputChange = this.handleInputChange.bind(this);&lt;br /&gt;
   }&lt;br /&gt;
   handleInputChange(event) {&lt;br /&gt;
     const target = event.target;&lt;br /&gt;
     const value = (target.type == 'checkbox') ? target.checked : target.value;&lt;br /&gt;
     const name = target.name;&lt;br /&gt;
     this.setState({[name]: value});&lt;br /&gt;
   }&lt;br /&gt;
   render(){&lt;br /&gt;
     return (&lt;br /&gt;
       &amp;amp;lt;form&amp;amp;gt;&lt;br /&gt;
         &amp;amp;lt;label&amp;amp;gt;Is going:&amp;amp;lt;input name=&amp;quot;isGoing&amp;quot; type=&amp;quot;checkbox&amp;quot; checked={this.state.isGoing} onChange={this.handleInputChange}/&amp;amp;gt;&amp;amp;lt;/label&amp;amp;gt;&lt;br /&gt;
         &amp;amp;lt;br /&amp;amp;gt;&lt;br /&gt;
         &amp;amp;lt;label&amp;amp;gt;Number of guests:&amp;amp;lt;input name=&amp;quot;numberOfGuests&amp;quot; type=&amp;quot;number&amp;quot; value={this.state.numberOfGuests} onChange={this.handleInputChange}/&amp;amp;gt;&amp;amp;lt;/label&amp;amp;gt;&lt;br /&gt;
       &amp;amp;lt;/form&amp;amp;gt;&lt;br /&gt;
     );&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
 [[React]]DOM.render(&lt;br /&gt;
   &amp;amp;lt;div&amp;amp;gt;&lt;br /&gt;
     &amp;amp;lt;[[R]]eservation /&amp;amp;gt;&lt;br /&gt;
   &amp;amp;lt;/div&amp;amp;gt;,&lt;br /&gt;
   document.getElementById('root')&lt;br /&gt;
 );&lt;br /&gt;
[[File:1098_react13.jpg]]&lt;br /&gt;
====コントロールされたコンポーネント以外の方法====&lt;br /&gt;
*コントロールされたコンポーネントを利用するのが、冗長な場合がある。&lt;br /&gt;
*入力フォームを実装するための、[https://facebook.github.io/react/docs/uncontrolled-components.html コントロールされないコンポーネント]を参照。&lt;br /&gt;
===状態を持ち上げる===&lt;br /&gt;
*いくつかのコンポーネントは同じ変更をデータに反映させることを必要とする。&lt;br /&gt;
*共有状態をそれらの、最も近い共通の祖先に持ち上げることを推奨する。&lt;br /&gt;
=====水が沸騰しているかどうかの計算を行う。=====&lt;br /&gt;
 function BoilingVerdict(props) {&lt;br /&gt;
   if (props.celsius &amp;amp;gt;= 100) {&lt;br /&gt;
     return &amp;amp;lt;p&amp;amp;gt;The water would boil.&amp;amp;lt;/p&amp;amp;gt;;&lt;br /&gt;
   }&lt;br /&gt;
   return &amp;amp;lt;p&amp;amp;gt;The water would not boil.&amp;amp;lt;/p&amp;amp;gt;&lt;br /&gt;
 }&lt;br /&gt;
 class Calculator extends [[React]].Component {&lt;br /&gt;
   constructor(props) {&lt;br /&gt;
     super(props);&lt;br /&gt;
     this.handleChange = this.handleChange.bind(this);&lt;br /&gt;
     this.state = {temprature: ''};&lt;br /&gt;
   }&lt;br /&gt;
   handleChange(e){&lt;br /&gt;
     this.setState({temprature: e.target.value});&lt;br /&gt;
   }&lt;br /&gt;
   render(){&lt;br /&gt;
     const temprature = this.state.temprature;&lt;br /&gt;
     return (&lt;br /&gt;
       &amp;amp;lt;fieldset&amp;amp;gt;&lt;br /&gt;
         &amp;amp;lt;legend&amp;amp;gt;Enter temprature in Celsius:&amp;amp;lt;/legend&amp;amp;gt;&lt;br /&gt;
         &amp;amp;lt;input value={temprature} onChange={this.handleChange} /&amp;amp;gt;&lt;br /&gt;
         &amp;amp;lt;BoilingVerdict celsius={parseFloat(temprature)} /&amp;amp;gt;  &lt;br /&gt;
       &amp;amp;lt;/fieldset&amp;amp;gt;&lt;br /&gt;
     );&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
 [[React]]DOM.render(&lt;br /&gt;
   &amp;amp;lt;div&amp;amp;gt;&lt;br /&gt;
     &amp;amp;lt;Calculator /&amp;amp;gt;&lt;br /&gt;
   &amp;amp;lt;/div&amp;amp;gt;,&lt;br /&gt;
   document.getElementById('root')&lt;br /&gt;
 );&lt;br /&gt;
[[File:1099_react14.jpg]]&lt;br /&gt;
====2つ目の入力を追加する====&lt;br /&gt;
*華氏の入力を追加し同期させる&lt;br /&gt;
*[[React]]でstateを共有するには、共通の祖先に移動させることで実現でき、「状態の持ち上げ」という&lt;br /&gt;
*TempratureInputのローカルstateをCalcuratorへ移動させる&lt;br /&gt;
*Calucratorの共有stateは、「真の情報源」となる&lt;br /&gt;
*TempratureInputにとって、tempuratureがローカルの場合、propsは読み取り専用となるので、this.setState()とするしかないが、tempratureが、親のpropsなので、管理する必要はなくなる。&lt;br /&gt;
 const scaleName = {&lt;br /&gt;
   c: '摂氏',&lt;br /&gt;
   f: '華氏'&lt;br /&gt;
 };&lt;br /&gt;
 function BoilingVerdict(props) {&lt;br /&gt;
   if (props.celsius &amp;amp;gt;= 100) {&lt;br /&gt;
     return &amp;amp;lt;p&amp;amp;gt;The water would boil.&amp;amp;lt;/p&amp;amp;gt;;&lt;br /&gt;
   }&lt;br /&gt;
   return &amp;amp;lt;p&amp;amp;gt;The water would not boil.&amp;amp;lt;/p&amp;amp;gt;&lt;br /&gt;
 }&lt;br /&gt;
 function toCelsius(fahrenheit) {&lt;br /&gt;
   return (fahrenheit - 32) * 5/9;&lt;br /&gt;
 }&lt;br /&gt;
 function toFahrenheit(celsius) {&lt;br /&gt;
   return (celsius * 9/5) + 32;&lt;br /&gt;
 }&lt;br /&gt;
 function tryConvert(temprature, convert) {&lt;br /&gt;
   const input = parseFloat(temprature);&lt;br /&gt;
   if (Number.isNaN(input)) {&lt;br /&gt;
     return '';&lt;br /&gt;
   }&lt;br /&gt;
   const output = convert(input);&lt;br /&gt;
   const rounded = Math.round(output * 1000) / 1000;&lt;br /&gt;
   return rounded.toString();&lt;br /&gt;
 }&lt;br /&gt;
 class TempratureInput extends [[React]].Component {&lt;br /&gt;
   constructor(props) {&lt;br /&gt;
     super(props);&lt;br /&gt;
     this.handleChange = this.handleChange.bind(this);&lt;br /&gt;
     this.state = {temprature: ''};&lt;br /&gt;
   }&lt;br /&gt;
   handleChange(e){&lt;br /&gt;
     // before:this.setState({temprature: e.target.value});&lt;br /&gt;
     this.props.onTempratureChange(e.target.value);&lt;br /&gt;
   }&lt;br /&gt;
   render(){&lt;br /&gt;
     // before:const temprature = this.state.temprature;&lt;br /&gt;
     const temprature = this.props.temprature;&lt;br /&gt;
     const scale = this.props.scale;&lt;br /&gt;
     return (&lt;br /&gt;
       &amp;amp;lt;fieldset&amp;amp;gt;&lt;br /&gt;
         &amp;amp;lt;legend&amp;amp;gt;Enter temprature in {scaleName[scale]}:&amp;amp;lt;/legend&amp;amp;gt;&lt;br /&gt;
         &amp;amp;lt;input value={temprature} onChange={this.handleChange} /&amp;amp;gt;&lt;br /&gt;
         &amp;amp;lt;BoilingVerdict celsius={parseFloat(temprature)} /&amp;amp;gt;  &lt;br /&gt;
       &amp;amp;lt;/fieldset&amp;amp;gt;&lt;br /&gt;
     );&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
 class Calculator extends [[React]].Component {&lt;br /&gt;
   constructor(props) {&lt;br /&gt;
     super(props);&lt;br /&gt;
     this.handleCelsiumChange = this.handleCelsiumChange.bind(this);&lt;br /&gt;
     this.handlFahrenheitChange = this.handlFahrenheitChange.bind(this);&lt;br /&gt;
     this.state = {scale:'c', temprature:''};&lt;br /&gt;
   }&lt;br /&gt;
   handleCelsiumChange(temprature) {&lt;br /&gt;
     this.setState({scale:'c', temprature});&lt;br /&gt;
   }&lt;br /&gt;
   handlFahrenheitChange(temprature) {&lt;br /&gt;
     this.setState({scale:'f', temprature});&lt;br /&gt;
   }&lt;br /&gt;
   render() {&lt;br /&gt;
     const scale = this.state.scale;&lt;br /&gt;
     const temprature = this.state.temprature;&lt;br /&gt;
     const celsius = scale == 'f' ? tryConvert(temprature, toCelsius) : temprature;&lt;br /&gt;
     const fahrenheit = scale == 'c' ? tryConvert(temprature, toFahrenheit) : temprature;&lt;br /&gt;
     return (&lt;br /&gt;
       &amp;amp;lt;div&amp;amp;gt;&lt;br /&gt;
         &amp;amp;lt;TempratureInput scale=&amp;quot;c&amp;quot; temprature={celsius} onTempratureChange={this.handleCelsiumChange} /&amp;amp;gt;&lt;br /&gt;
         &amp;amp;lt;TempratureInput scale=&amp;quot;f&amp;quot; temprature={fahrenheit} onTempratureChange={this.handlFahrenheitChange}/&amp;amp;gt;&lt;br /&gt;
         &amp;amp;lt;BoilingVerdict celsius={parseFloat(celsius)} /&amp;amp;gt;&lt;br /&gt;
       &amp;amp;lt;/div&amp;amp;gt;&lt;br /&gt;
     );&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
 [[React]]DOM.render(&lt;br /&gt;
   &amp;amp;lt;div&amp;amp;gt;&lt;br /&gt;
     &amp;amp;lt;Calculator /&amp;amp;gt;&lt;br /&gt;
   &amp;amp;lt;/div&amp;amp;gt;,&lt;br /&gt;
   document.getElementById('root')&lt;br /&gt;
 );&lt;br /&gt;
[[File:1100_react15.jpg]]&lt;br /&gt;
===コンポジションと継承===&lt;br /&gt;
*[[React]]は強力なコンポジションモデルをもつ。コンポーネントの再利用には継承よりコンポジションを推奨する&lt;br /&gt;
====封じ込める====&lt;br /&gt;
*一部のコンポーネントは自身の子供を事前に知ることができない&lt;br /&gt;
*これは、特にサイドバーやダイアログなどボックスを表現するコンポーネント共通&lt;br /&gt;
*このようなコンポーネントには特別な子供propを使用し直接その要素に出力する&lt;br /&gt;
*&amp;amp;lt;FancyBorder&amp;amp;gt;の内側に何があっても、JSXタグはFancyBorderコンポーネントをprops.children として経由する&lt;br /&gt;
 &amp;amp;lt;style type=&amp;quot;text/css&amp;quot;&amp;amp;gt;&lt;br /&gt;
   div.FancyBorder {&lt;br /&gt;
     border : 2px dashed;&lt;br /&gt;
   }&lt;br /&gt;
   div.FancyBorder-blue {&lt;br /&gt;
     border-color: blue;&lt;br /&gt;
   }&lt;br /&gt;
 &amp;amp;lt;/style&amp;amp;gt;&lt;br /&gt;
&lt;br /&gt;
 function FancyBorder(props) {&lt;br /&gt;
   return (&lt;br /&gt;
     &amp;amp;lt;div className={'FancyBorder FancyBorder-' + props.color}&amp;amp;gt;&lt;br /&gt;
       {props.children}&lt;br /&gt;
     &amp;amp;lt;/div&amp;amp;gt;&lt;br /&gt;
   );&lt;br /&gt;
 }&lt;br /&gt;
 function WelcomDialog() {&lt;br /&gt;
   return (&lt;br /&gt;
     &amp;amp;lt;FancyBorder color=&amp;quot;blue&amp;quot;&amp;amp;gt;&lt;br /&gt;
       &amp;amp;lt;h1 className=&amp;quot;Dialog-title&amp;quot;&amp;amp;gt;Welcome&amp;amp;lt;/h1&amp;amp;gt;&lt;br /&gt;
     &amp;amp;lt;/FancyBorder&amp;amp;gt;&lt;br /&gt;
   );&lt;br /&gt;
 }&lt;br /&gt;
 [[React]]DOM.render(&lt;br /&gt;
   &amp;amp;lt;div&amp;amp;gt;&lt;br /&gt;
     &amp;amp;lt;WelcomDialog /&amp;amp;gt;&lt;br /&gt;
   &amp;amp;lt;/div&amp;amp;gt;,&lt;br /&gt;
   document.getElementById('root')&lt;br /&gt;
 );&lt;br /&gt;
[[File:1101_react16.jpg]]&lt;br /&gt;
====特殊化====&lt;br /&gt;
*コンポーネントを他のコンポーネントの特殊なものとして考えることがある、例えば、WelcomDialogはDialogの特殊な例として。&lt;br /&gt;
*[[React]]では、コンポジションを使って実現する&lt;br /&gt;
*クラスを用いても同様に記述できる&lt;br /&gt;
 function Dialog(props) {&lt;br /&gt;
   return (&lt;br /&gt;
     &amp;amp;lt;FancyBorder color=&amp;quot;blue&amp;quot;&amp;amp;gt;&lt;br /&gt;
       &amp;amp;lt;h1 className=&amp;quot;Dialog-title&amp;quot;&amp;amp;gt;{props.title}&amp;amp;lt;/h1&amp;amp;gt;&lt;br /&gt;
     &amp;amp;lt;/FancyBorder&amp;amp;gt;&lt;br /&gt;
   );&lt;br /&gt;
 }&lt;br /&gt;
 function FancyBorder(props) {&lt;br /&gt;
   return (&lt;br /&gt;
     &amp;amp;lt;div className={'FancyBorder FancyBorder-' + props.color}&amp;amp;gt;&lt;br /&gt;
       {props.children}&lt;br /&gt;
     &amp;amp;lt;/div&amp;amp;gt;&lt;br /&gt;
   );&lt;br /&gt;
 }&lt;br /&gt;
 function WelcomDialog() {&lt;br /&gt;
   return (&lt;br /&gt;
     &amp;amp;lt;Dialog title=&amp;quot;Welcome&amp;quot; /&amp;amp;gt;&lt;br /&gt;
   );&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
===[[React Router]]===&lt;br /&gt;
*[[React Router]]&lt;br /&gt;
===[[Redux]]===&lt;br /&gt;
*[[Redux]]&lt;br /&gt;
===[[Tips]]===&lt;br /&gt;
*[http://typea.info/blg/glob/2017/06/react.html React のシンタックスエラーをデバッグ]&lt;br /&gt;
&lt;br /&gt;
{{ref example.zip}}&lt;br /&gt;
====ビルド====&lt;br /&gt;
*https://mae.chab.in/archives/2765&lt;br /&gt;
*https://mae.chab.in/archives/2891&lt;/div&gt;</summary>
		<author><name>Piroto</name></author>
		
	</entry>
	<entry>
		<id>https://www.typea.info/tips_/index.php?title=React&amp;diff=35331</id>
		<title>React</title>
		<link rel="alternate" type="text/html" href="https://www.typea.info/tips_/index.php?title=React&amp;diff=35331"/>
		<updated>2024-10-05T08:47:43Z</updated>

		<summary type="html">&lt;p&gt;Piroto: /* TypeScriptの導入 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==[[React]]==&lt;br /&gt;
[[Node.js]] | [[Next.js]] |&lt;br /&gt;
&lt;br /&gt;
{{amazon|4873117887}}&lt;br /&gt;
&lt;br /&gt;
{{amazon|4815619484}}&lt;br /&gt;
&lt;br /&gt;
===スケルトン作成===&lt;br /&gt;
#[https://www.typea.info/blog/index.php/2017/08/15/react_1/ 開発の全体像を把握しつつ開発環境を整える]&lt;br /&gt;
#[https://www.typea.info/blog/index.php/2017/08/16/react_router/ React の単純なサンプルに React Router を適用する]&lt;br /&gt;
#[https://www.typea.info/blog/index.php/2017/08/17/react_react_router_redux-saga/ React の単純なサンプルに React Router を組み込んだものに Redux-Saga を適用する]&lt;br /&gt;
#[https://www.typea.info/blog/index.php/2017/08/19/react_react_router_redux-saga_ajax/ React の単純なサンプルに React Router を組み込んだものに Redux-Saga を適用したものからAjax通信を組み込む]&lt;br /&gt;
#[https://www.typea.info/blog/index.php/2017/08/23/react-react_router-redux-saga-superagent_bootstrap/ React環境-&amp;amp;gt;React Router-&amp;amp;gt;Redux-Saga-&amp;amp;gt;SuperAgent に Bootstrapを適用する]&lt;br /&gt;
&lt;br /&gt;
==導入==&lt;br /&gt;
&lt;br /&gt;
===Create React App===&lt;br /&gt;
*Reactアプリ開発のためのコマンドラインツール。トランスパイラ、バンドラ、開発サーバーなどを含むツールチェーン&lt;br /&gt;
*Facebook本家が提供。他にもNext.js、Vite、Gatsby、Parcelなどのツールチェーンがある。&lt;br /&gt;
*より高度な環境としてNext.jsも存在&lt;br /&gt;
&lt;br /&gt;
===Next.js===&lt;br /&gt;
*[[Next.js]]&lt;br /&gt;
*Reactは、あくまでUI部分のみ&lt;br /&gt;
*本格的なアプリ開発には周辺領域を担うためのフレームワークが必要&lt;br /&gt;
*Reactベースのフレームワークとしてデファクトスタンダードと言える存在&lt;br /&gt;
*主なライブラリ&lt;br /&gt;
**ファイルシステムベースの設定レスルーター&lt;br /&gt;
**サーバーコンポーネント&lt;br /&gt;
**データ取得用fetchメソッド&lt;br /&gt;
**リソース組み込みの自動最適化&lt;br /&gt;
**CSSフレームワーク、Tailwind　CSSへの標準対応&lt;br /&gt;
&lt;br /&gt;
===Node===&lt;br /&gt;
[[Node.js]] のインストール&lt;br /&gt;
&lt;br /&gt;
====npx====&lt;br /&gt;
*ローカルにインストールされたツールを実行するためのパッケージランナー&lt;br /&gt;
&lt;br /&gt;
===Next.jsアプリの作成===&lt;br /&gt;
[[Next.js]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===[[TypeScript]]の導入===&lt;br /&gt;
====ファイル拡張子====&lt;br /&gt;
*https://3chome.net/javascript-typescript/#:~:text=.tsx%EF%BC%88TSX%E3%83%95%E3%82%A1&lt;br /&gt;
*[[TypeScript]]の拡張子&lt;br /&gt;
**.ts :　コードにJSX含まない&lt;br /&gt;
**.tsx :　コードにJSX含む(含まない場合tsxとしてもよいが望ましくない)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====型アサーション====&lt;br /&gt;
&lt;br /&gt;
===導入(旧)===&lt;br /&gt;
----&lt;br /&gt;
*https://facebook.github.io/react/docs/installation.html&lt;br /&gt;
*https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/[[R]]EADME.md#table-of-contents&lt;br /&gt;
*[[React]]のSPAを作成するのによい方法&lt;br /&gt;
 [[npm]] install -g create-react-app&lt;br /&gt;
*https://ja.reactjs.org/docs/create-a-new-react-app.html&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
npx create-react-app my-app&lt;br /&gt;
cd my-app&lt;br /&gt;
npm start&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
*[[React]]はバックエンドロジックやデータベースを持たないが、使いたいものを使えばよい。&lt;br /&gt;
*Babelやwebpackのようなビルドツールも設定なしに利用できる。&lt;br /&gt;
 PS C:\workspaces\vscode\reactlesson&amp;amp;gt; create-react-app react-lesson&lt;br /&gt;
 Creating a new [[React]] app in C:\workspaces\vscode\reactlesson\react-lesson.&lt;br /&gt;
 &lt;br /&gt;
 Installing packages. This might take a couple minutes.&lt;br /&gt;
 Installing react, react-dom, and react-scripts...&lt;br /&gt;
               :&lt;br /&gt;
*アプリケーションが作成されたら実行&lt;br /&gt;
 PS C:\workspaces\vscode\reactlesson&amp;amp;gt; cd react-lesson&lt;br /&gt;
 PS C:\workspaces\vscode\reactlesson&amp;amp;gt; [[npm]] start&lt;br /&gt;
*実行された&lt;br /&gt;
[[File:1086_react01.jpg]]&lt;br /&gt;
*/src/App.js を書き換えてみる&lt;br /&gt;
 import [[React]], { Component } from 'react';&lt;br /&gt;
 import logo from './logo.svg';&lt;br /&gt;
 import './App.css';&lt;br /&gt;
 &lt;br /&gt;
 const element = (&amp;amp;lt;h1&amp;amp;gt;Hello,world&amp;amp;lt;/h1&amp;amp;gt;);&lt;br /&gt;
 class App extends Component {&lt;br /&gt;
   render() {&lt;br /&gt;
     return (&lt;br /&gt;
       element&lt;br /&gt;
     );&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 export default App;&lt;br /&gt;
*反映された&lt;br /&gt;
[[File:1087_react02.jpg]]&lt;br /&gt;
*リリース準備ができたら、以下を実行することで、buildフォルダ以下に最適化されたアプリケーションを作成する&lt;br /&gt;
 [[npm]] run build&lt;br /&gt;
&lt;br /&gt;
==クイックスタート==&lt;br /&gt;
===JSX===&lt;br /&gt;
 const element = &amp;amp;lt;h1&amp;amp;gt;Hello,world!&amp;amp;lt;/h1&amp;amp;gt;;&lt;br /&gt;
*文字列でも、[[HTML]]でもなく、JSX&lt;br /&gt;
*[[JavaScript]]の拡張文法&lt;br /&gt;
*テンプレートと思われるかもしれないが、完全な[[JavaScript]]&lt;br /&gt;
*JSXは[[React]]の要素を生成する&lt;br /&gt;
===JSX表現===&lt;br /&gt;
*どのような[[JavaScript]]の表現も、中括弧で囲むことでJSXに埋め込むことができる&lt;br /&gt;
*const element = (&amp;amp;lt;h1&amp;amp;gt;Hello, {formatName(user)}!&amp;amp;lt;/h1&amp;amp;gt;);&lt;br /&gt;
&lt;br /&gt;
 &amp;amp;lt;!DOCTYPE html&amp;amp;gt;&lt;br /&gt;
 &amp;amp;lt;html&amp;amp;gt;&lt;br /&gt;
   &amp;amp;lt;head&amp;amp;gt;&lt;br /&gt;
     &amp;amp;lt;meta charset=&amp;quot;UTF-8&amp;quot; /&amp;amp;gt;&lt;br /&gt;
     &amp;amp;lt;title&amp;amp;gt;Hello World&amp;amp;lt;/title&amp;amp;gt;&lt;br /&gt;
     &amp;amp;lt;script src=&amp;quot;https://unpkg.com/react@latest/dist/react.js&amp;quot;&amp;amp;gt;&amp;amp;lt;/script&amp;amp;gt;&lt;br /&gt;
     &amp;amp;lt;script src=&amp;quot;https://unpkg.com/react-dom@latest/dist/react-dom.js&amp;quot;&amp;amp;gt;&amp;amp;lt;/script&amp;amp;gt;&lt;br /&gt;
     &amp;amp;lt;script src=&amp;quot;https://unpkg.com/babel-standalone@6.15.0/babel.min.js&amp;quot;&amp;amp;gt;&amp;amp;lt;/script&amp;amp;gt;&lt;br /&gt;
   &amp;amp;lt;/head&amp;amp;gt;&lt;br /&gt;
   &amp;amp;lt;body&amp;amp;gt;&lt;br /&gt;
     &amp;amp;lt;div id=&amp;quot;root&amp;quot;&amp;amp;gt;&amp;amp;lt;/div&amp;amp;gt;&lt;br /&gt;
     &amp;amp;lt;script type=&amp;quot;text/babel&amp;quot;&amp;amp;gt;&lt;br /&gt;
     function formatName(user) {&lt;br /&gt;
         return user.firstName + ' ' + user.lastName;&lt;br /&gt;
     }&lt;br /&gt;
     const user = {firstName:'Hiroto', lastName:'Yagi'};&lt;br /&gt;
     const element = (&amp;amp;lt;h1&amp;amp;gt;Hello, {formatName(user)}!&amp;amp;lt;/h1&amp;amp;gt;); &lt;br /&gt;
     [[React]]DOM.render(&lt;br /&gt;
         element,&lt;br /&gt;
         document.getElementById('root')&lt;br /&gt;
     );&lt;br /&gt;
     &amp;amp;lt;/script&amp;amp;gt;&lt;br /&gt;
   &amp;amp;lt;/body&amp;amp;gt;&lt;br /&gt;
 &amp;amp;lt;/html&amp;amp;gt;&lt;br /&gt;
&lt;br /&gt;
*コンパイルされたJSXは通常の[[JavaScript]]オブジェクト&lt;br /&gt;
*JSXをif文やforループ、変数への割り当て、引数や戻り値に利用できる&lt;br /&gt;
&lt;br /&gt;
 function greeting(user) {&lt;br /&gt;
    var now = new Date();&lt;br /&gt;
    if (5 &amp;amp;lt;= now.getHours() &amp;amp;&amp;amp; now.getHours() &amp;amp;lt;= 12) {&lt;br /&gt;
        return &amp;amp;lt;h1&amp;amp;gt; Good morning {user.firstName + ' ' + user.lastName}.&amp;amp;lt;/h1&amp;amp;gt;;&lt;br /&gt;
    } else {&lt;br /&gt;
        return &amp;amp;lt;h1&amp;amp;gt; Hello {user.firstName + ' ' + user.lastName}.&amp;amp;lt;/h1&amp;amp;gt;;&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
====属性に利用====&lt;br /&gt;
*中括弧を利用して、二重引用符なし(使用すると文字列リテラルとして扱われる)で直接利用できる。&lt;br /&gt;
 &amp;amp;lt;div id=&amp;quot;root&amp;quot;&amp;amp;gt;&amp;amp;lt;/div&amp;amp;gt;&lt;br /&gt;
 &amp;amp;lt;script type=&amp;quot;text/babel&amp;quot;&amp;amp;gt;&lt;br /&gt;
 function greeting(user) {&lt;br /&gt;
     var now = new Date();&lt;br /&gt;
     if (5 &amp;amp;lt;= now.getHours() &amp;amp;&amp;amp; now.getHours() &amp;amp;lt;= 12) {&lt;br /&gt;
         return &amp;amp;lt;h1&amp;amp;gt; Good morning &amp;amp;lt;a href={user.webpageUrl}&amp;amp;gt;{user.firstName + ' ' + user.lastName}&amp;amp;lt;/a&amp;amp;gt;.&amp;amp;lt;/h1&amp;amp;gt;;&lt;br /&gt;
     } else {&lt;br /&gt;
         return &amp;amp;lt;h1&amp;amp;gt; Hello &amp;amp;lt;a href={user.webpageUrl}&amp;amp;gt;{user.firstName + ' ' + user.lastName}&amp;amp;lt;/a&amp;amp;gt;.&amp;amp;lt;/h1&amp;amp;gt;;&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
 const user = {firstName:'Hiroto', lastName:'Yagi', webpageUrl:'http://typea.info'};&lt;br /&gt;
 const element = (&amp;amp;lt;h1&amp;amp;gt;{greeting(user)}&amp;amp;lt;/h1&amp;amp;gt;); &lt;br /&gt;
 [[React]]DOM.render(&lt;br /&gt;
     element,&lt;br /&gt;
     document.getElementById('root')&lt;br /&gt;
 );&lt;br /&gt;
[[File:1089_react04.jpg]]&lt;br /&gt;
====子要素====&lt;br /&gt;
*子要素がない場合、[[XML]]同様　/&amp;amp;gt; で閉じる&lt;br /&gt;
*子要素を含む&lt;br /&gt;
*JSXはHTMLより[[JavaScript]]により近い。ReactDOMはキャメルケースプロパティ(HTMLでは、class がclassName、HTMLではtabindexがtabIndexなど)を持つ&lt;br /&gt;
 function greeting(user) {&lt;br /&gt;
     return &amp;amp;lt;div&amp;amp;gt;&lt;br /&gt;
             &amp;amp;lt;h1&amp;amp;gt; Good morning {user.firstName + ' ' + user.lastName}.&amp;amp;lt;/h1&amp;amp;gt;&lt;br /&gt;
             &amp;amp;lt;h2&amp;amp;gt;&amp;amp;lt;a href={user.webpageUrl}&amp;amp;gt;webpage&amp;amp;lt;/a&amp;amp;gt;&amp;amp;lt;/h2&amp;amp;gt;&lt;br /&gt;
            &amp;amp;lt;/div&amp;amp;gt;&lt;br /&gt;
            ;&lt;br /&gt;
 }&lt;br /&gt;
 const user = {firstName:'Hiroto', lastName:'Yagi', webpageUrl:'http://typea.info'};&lt;br /&gt;
 const element = (greeting(user)); &lt;br /&gt;
 [[React]]DOM.render(&lt;br /&gt;
     element,&lt;br /&gt;
     document.getElementById('root')&lt;br /&gt;
 );&lt;br /&gt;
[[File:1090_react05.jpg]]&lt;br /&gt;
====インジェクション[[攻撃]]の予防====&lt;br /&gt;
*デフォルトで[[React]] DOMは、JSXに埋め込まれた値をレンダリング前にエスケープする&lt;br /&gt;
*明示的にアプリケーションに記述しなくてもインジェクションされないことを保証する&lt;br /&gt;
*XSS[[攻撃]]の予防を助ける&lt;br /&gt;
 function greeting(user, title) {&lt;br /&gt;
     return &amp;amp;lt;div&amp;amp;gt;&lt;br /&gt;
              &amp;amp;lt;h1&amp;amp;gt;{title}&amp;amp;lt;/h1&amp;amp;gt;&lt;br /&gt;
              &amp;amp;lt;h2&amp;amp;gt; Good morning {user.firstName + ' ' + user.lastName}.&amp;amp;lt;/h2&amp;amp;gt;&lt;br /&gt;
              &amp;amp;lt;h2&amp;amp;gt;&amp;amp;lt;a href={user.webpageUrl}&amp;amp;gt;webpage&amp;amp;lt;/a&amp;amp;gt;&amp;amp;lt;/h2&amp;amp;gt;&lt;br /&gt;
            &amp;amp;lt;/div&amp;amp;gt;&lt;br /&gt;
            ;&lt;br /&gt;
 }&lt;br /&gt;
 const title = &amp;quot;&amp;amp;lt;input type='button'&amp;amp;gt;&amp;quot;;&lt;br /&gt;
 const user = {firstName:'Hiroto', lastName:'Yagi', webpageUrl:'http://typea.info'};&lt;br /&gt;
 const element = (greeting(user,title)); &lt;br /&gt;
 [[React]]DOM.render(&lt;br /&gt;
     element,&lt;br /&gt;
     document.getElementById('root')&lt;br /&gt;
 );&lt;br /&gt;
[[File:1091_react06.jpg]]&lt;br /&gt;
====JSX [[R]]epresent オブジェクト====&lt;br /&gt;
*Babelは、[[React]].createElement()を呼び出しコンパイルを行う&lt;br /&gt;
*以下の2つは同じ意味&lt;br /&gt;
 const element1 = (&amp;amp;lt;h1 className='greeting'&amp;amp;gt;hello&amp;amp;lt;/h1&amp;amp;gt;);&lt;br /&gt;
 const element2 = [[React]].createElement('h1',{className:'greeting'},'hello');&lt;br /&gt;
*[[React]].createElement()は、バグを防ぐ手助けをするが、本質的には以下のようなオブジェクトを生成する&lt;br /&gt;
 // 簡易表現&lt;br /&gt;
 const element = {type:'h1',props:{className:'greeting',children:'hello'}};&lt;br /&gt;
*これらの要素を&amp;quot;[[React]] elements&amp;quot;と呼ぶ&lt;br /&gt;
*画面に表示させたいものの記述と考えることができる&lt;br /&gt;
*[[React]]はこれらのオブジェクトを読み、DOMの構築と最新化に利用する    &lt;br /&gt;
===Elementsのレンダリング===&lt;br /&gt;
*Elements は[[React]] アプリケーションの最小のビルディングブロック&lt;br /&gt;
*1つの要素は、画面上に表示するものを表現する&lt;br /&gt;
*ブラウザのDOM要素と異なり、[[React]] Elements はプレーンなオブジェクトで生成のコストは小さい&lt;br /&gt;
*[[React]] DOMは、DOMを[[React]] Elementsに一致するように取り扱う&lt;br /&gt;
====1つの要素を[[DOM]]の中にレンダリング====&lt;br /&gt;
*[[HTML]]どこかに記述する、以下のDIV要素をroot DOM ノードと呼ぶ&lt;br /&gt;
*[[React]] DOM が管理するすべてが、この要素の中にある&lt;br /&gt;
 &amp;amp;lt;div id=&amp;quot;root&amp;quot;&amp;amp;gt;&amp;amp;lt;/div&amp;amp;gt;&lt;br /&gt;
====[[React]]要素の更新====&lt;br /&gt;
*[[React]]要素は不変。一旦生成したら、子要素、属性などは変更できない。&lt;br /&gt;
*UIを更新するには、新しい要素を作成し、[[React]]DOM.rendar()に引き渡す。&lt;br /&gt;
 function tick() {&lt;br /&gt;
   const element = (&amp;amp;lt;div&amp;amp;gt;{(new Date()).toLocaleTimeString()}&amp;amp;lt;/div&amp;amp;gt;);&lt;br /&gt;
   [[React]]DOM.render(&lt;br /&gt;
       element,&lt;br /&gt;
       document.getElementById('root')&lt;br /&gt;
   );&lt;br /&gt;
 }&lt;br /&gt;
 setInterval(tick,1000);&lt;br /&gt;
[[File:1092_react07.jpg]]&lt;br /&gt;
&amp;amp;lt;blockquote&amp;amp;gt;通常の[[React]] アプリケーションでは、[[React]]DOM.rendar()は 一度しか呼びださない。&amp;amp;lt;/blockquote&amp;amp;gt;&lt;br /&gt;
====[[React]]は必要なもののみ更新する====&lt;br /&gt;
*[[React]] DOMは、要素および子要素を前の状態と比較し、DOMの更新が必要な個所にのみ適用する。&lt;br /&gt;
*ブラウザツールで、上記のソースコードを確認する&lt;br /&gt;
[[File:1093_react08.jpg]]&lt;br /&gt;
&amp;amp;lt;blockquote&amp;amp;gt;毎tick()の呼び出しで、すべてのUIツリーを生成するよう記述してるが、変更が発生したテキストノードのみ[[React]] DOMにより更新されている。&amp;amp;lt;/blockquote&amp;amp;gt;&lt;br /&gt;
===コンポーネントと Props===&lt;br /&gt;
*コンポーネントはUIを独立し再利用可能な部分に分割する。&lt;br /&gt;
*概念的にコンポーネントは[[JavaScript]]の関数のようなもの。&lt;br /&gt;
*コンポーネントはpropsと呼ばれる任意の入力を受け付け、[[React]] Elementを返す。&lt;br /&gt;
====コンポーネントの機能とクラス====&lt;br /&gt;
*[[JavaScript]]の関数としてコンポーネントを定義する&lt;br /&gt;
*この関数は有効な[[React]]コンポーネント、なぜなら、単一のprops引数を引数として取り、[[React]] Elementを返す。&lt;br /&gt;
*このようなコンポーネントを&amp;quot;functional&amp;quot;と呼ぶ。&lt;br /&gt;
 function Welcome(props) {&lt;br /&gt;
     return &amp;amp;lt;h1&amp;amp;gt;Hello,{props.name}&amp;amp;lt;/h1&amp;amp;gt;;&lt;br /&gt;
 }&lt;br /&gt;
*ES6のクラスをコンポーネントの定義として利用できる&lt;br /&gt;
 class Welcome extends [[React]].Component {&lt;br /&gt;
     render() {&lt;br /&gt;
         return &amp;amp;lt;h1&amp;amp;gt;Hello,{props.name}&amp;amp;lt;/h1&amp;amp;gt;;&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
*上記2つのコンポーネントは[[React]]の視点からは同じ&lt;br /&gt;
====コンポーネントのレンダリング====&lt;br /&gt;
*Elementは、ユーザー定義コンポーネントも表すことができる&lt;br /&gt;
 function Welcome(props) {&lt;br /&gt;
  return &amp;amp;lt;h1&amp;amp;gt;Hello,{props.name}&amp;amp;lt;/h1&amp;amp;gt;;&lt;br /&gt;
 }&lt;br /&gt;
 const element = &amp;amp;lt;Welcome name='Hiroto' /&amp;amp;gt;&lt;br /&gt;
 [[React]]DOM.render(&lt;br /&gt;
     element,&lt;br /&gt;
     document.getElementById('root')&lt;br /&gt;
 );&lt;br /&gt;
*[[React]]がユーザー定義コンポーネントを表示するときに、JSXの属性からコンポーネントへ&amp;quot;props&amp;quot;としてオブジェクトが渡される。&lt;br /&gt;
&lt;br /&gt;
&amp;amp;lt;blockquote&amp;amp;gt;コンポーネント名はいつも大文字から始める。[[DOM]] タグは、&amp;amp;lt;div /&amp;amp;gt; だが、&amp;amp;lt;Welcome /&amp;amp;gt; はコンポーネントを表現する。Welcomeがスコープに存在すること。&amp;amp;lt;/blockquote&amp;amp;gt;&lt;br /&gt;
====コンポーネントの構成====&lt;br /&gt;
*コンポーネントはその出力において、他のコンポーネントに影響を与えることができる&lt;br /&gt;
*同じコンポーネントをどんなレベルの詳細にも抽象的に利用できる、ボタン、フォーム、ダイアログ、スクリーン&lt;br /&gt;
*[[React]]でこれらは、一般にコンポーネントで表現される&lt;br /&gt;
 function Welcome(props) {&lt;br /&gt;
   return &amp;amp;lt;h1&amp;amp;gt;Hello,{props.name}&amp;amp;lt;/h1&amp;amp;gt;;&lt;br /&gt;
 }&lt;br /&gt;
 function App() {&lt;br /&gt;
   return ( &amp;amp;lt;div&amp;amp;gt;&lt;br /&gt;
       &amp;amp;lt;Welcome name=&amp;quot;Yagi&amp;quot;/&amp;amp;gt;&lt;br /&gt;
       &amp;amp;lt;Welcome name=&amp;quot;Kaela&amp;quot;/&amp;amp;gt;&lt;br /&gt;
       &amp;amp;lt;Welcome name=&amp;quot;Hiroto&amp;quot;/&amp;amp;gt;&lt;br /&gt;
     &amp;amp;lt;/div&amp;amp;gt; );&lt;br /&gt;
 }&lt;br /&gt;
 [[React]]DOM.render(&lt;br /&gt;
     &amp;amp;lt;App /&amp;amp;gt;,&lt;br /&gt;
     document.getElementById('root')&lt;br /&gt;
 );&lt;br /&gt;
*一般的に新しい[[React]]アプリケーションは、一つのAppコンポーネントを最上位に持つ。既存のアプリケーションに[[React]]を統合する場合は、小さなコンポーネント、例えばButtonなど、ボトムアップから開始し、徐々にView階層の最上位にいたる。&lt;br /&gt;
&lt;br /&gt;
&amp;amp;lt;blockquote&amp;amp;gt;コンポーネントは、一つのroot要素を返さなければならない。上記で、Welcome要素を div に含めたのはこのため&amp;amp;lt;/blockquote&amp;amp;gt;&lt;br /&gt;
====Propsは読み取り専用====&lt;br /&gt;
**[[React]]はかなりフレキシブルだが、1つ厳格なルールがある。function だろうと class だろうとコンポーネントはpropsを編集できない。&lt;br /&gt;
===状態とライフサイクル===&lt;br /&gt;
*次のClockコンポーネントを再利用可能にカプセル化する&lt;br /&gt;
 function Clock(props) {&lt;br /&gt;
   return (&lt;br /&gt;
     &amp;amp;lt;div&amp;amp;gt;&lt;br /&gt;
       &amp;amp;lt;h2&amp;amp;gt;{props.date.toLocaleTimeString()}&amp;amp;lt;/h2&amp;amp;gt;&lt;br /&gt;
     &amp;amp;lt;/div&amp;amp;gt;&lt;br /&gt;
   );&lt;br /&gt;
 }&lt;br /&gt;
 function tick() {&lt;br /&gt;
   [[React]]DOM.render(&lt;br /&gt;
       &amp;amp;lt;Clock date={new Date()} /&amp;amp;gt;,&lt;br /&gt;
       document.getElementById('root')&lt;br /&gt;
   );&lt;br /&gt;
 }&lt;br /&gt;
 setInterval(tick, 1000);&lt;br /&gt;
&lt;br /&gt;
[[File:1094_react09.jpg]]&lt;br /&gt;
&lt;br /&gt;
*実装のために、Clockコンポーネントにstateを追加する。&lt;br /&gt;
*状態は、propsと同様だが、private かつ、コンポーネントから完全に制御される&lt;br /&gt;
*クラス宣言したコンポーネントにはいくつかの追加的な機能があるが、local state はこれにあたる&lt;br /&gt;
====関数をクラスに変更する====&lt;br /&gt;
#[[React]].Component を継承して同名のES6クラスを作成する&lt;br /&gt;
#render()メソッドを作成し、処理を移動、functionを削除&lt;br /&gt;
#propsをthis.propsに変更&lt;br /&gt;
 class Clock extends [[React]].Component {&lt;br /&gt;
   render() {&lt;br /&gt;
     return (&lt;br /&gt;
       &amp;amp;lt;div&amp;amp;gt;&lt;br /&gt;
         &amp;amp;lt;h2&amp;amp;gt;{this.props.date.toLocaleTimeString()}&amp;amp;lt;/h2&amp;amp;gt;&lt;br /&gt;
       &amp;amp;lt;/div&amp;amp;gt;&lt;br /&gt;
     );&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
====クラスにローカル状態を追加する====&lt;br /&gt;
*date を props から state へ移動する&lt;br /&gt;
#render()メソッドの中の、this.props.date を this.state.date に変更&lt;br /&gt;
#クラスにコンストラクタを追加し、this.stateの初期状態を記述する&lt;br /&gt;
#&amp;amp;lt;Clock date={new Date()} /&amp;amp;gt; から dateを削除&lt;br /&gt;
 class Clock extends [[React]].Component {&lt;br /&gt;
   constructor(props) {&lt;br /&gt;
     super(props);&lt;br /&gt;
     this.state = {date : new Date()};&lt;br /&gt;
   }&lt;br /&gt;
   render() {&lt;br /&gt;
     return (&lt;br /&gt;
       &amp;amp;lt;div&amp;amp;gt;&lt;br /&gt;
         &amp;amp;lt;h2&amp;amp;gt;{this.state.date.toLocaleTimeString()}&amp;amp;lt;/h2&amp;amp;gt;&lt;br /&gt;
       &amp;amp;lt;/div&amp;amp;gt;&lt;br /&gt;
     );&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
====クラスにライフサイクルメソッドを追加する====&lt;br /&gt;
*多くのコンポーネントを使用するアプリケーションでは、破棄されたコンポーネントのリソースの解放が重要&lt;br /&gt;
*ClockがDOMに最初にレンダリングされるときには、必ずタイマーをセットアップしたい。これを[[React]]では、&amp;quot;mounting&amp;quot; という&lt;br /&gt;
*また、ClockがDOMから取り除かれるときには、タイマーをクリアしたい。これを[[React]]では、&amp;quot;unmounting&amp;quot;という&lt;br /&gt;
*コンポーネントが、mount/unmount されるときに実行される特別なメソッドをクラスに宣言できる&lt;br /&gt;
*componentDidMount()、componentWillUnmount() これらのメソッドはライフサイクルフックと呼ばれる&lt;br /&gt;
*どのようにtimer IDを thisに保存するか&lt;br /&gt;
**this.propsが[[React]]によりセットアップされる間、this.stateは特別な意味を持つ&lt;br /&gt;
**表示に使用しないならば、クラスに自由にフィールドを追加できる&lt;br /&gt;
**render()の中では、それらは利用できないし、ステートも持たない&lt;br /&gt;
*最後に、毎秒実行されるtick()メソッドを実装する。&lt;br /&gt;
*this.setState()でローカルコンポーネントの状態を更新する&lt;br /&gt;
&lt;br /&gt;
 class Clock extends [[React]].Component {&lt;br /&gt;
   constructor(props) {&lt;br /&gt;
     super(props);&lt;br /&gt;
     this.state = {date : new Date()};&lt;br /&gt;
   }&lt;br /&gt;
   componentDidMount() {&lt;br /&gt;
     this.timerID = setInterval(&lt;br /&gt;
       () =&amp;amp;gt; this.tick(),1000&lt;br /&gt;
     );&lt;br /&gt;
   }&lt;br /&gt;
   componentWillUnmount() {&lt;br /&gt;
     clearInterval(this.timerID);&lt;br /&gt;
   }&lt;br /&gt;
   tick() {&lt;br /&gt;
     this.setState({&lt;br /&gt;
       date: new Date()&lt;br /&gt;
     });&lt;br /&gt;
   }&lt;br /&gt;
   render() {&lt;br /&gt;
     return (&lt;br /&gt;
       &amp;amp;lt;div&amp;amp;gt;&lt;br /&gt;
         &amp;amp;lt;h2&amp;amp;gt;{this.state.date.toLocaleTimeString()}&amp;amp;lt;/h2&amp;amp;gt;&lt;br /&gt;
       &amp;amp;lt;/div&amp;amp;gt;&lt;br /&gt;
     );&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
 [[React]]DOM.render(&lt;br /&gt;
   &amp;amp;lt;Clock /&amp;amp;gt;,&lt;br /&gt;
   document.getElementById('root')&lt;br /&gt;
 );&lt;br /&gt;
====状態を正しく使う====&lt;br /&gt;
=====stateを直接操作しない=====&lt;br /&gt;
 // まちがい&lt;br /&gt;
 this.state.comment = 'Hello';&lt;br /&gt;
*上記の代わりに、setState() を利用する&lt;br /&gt;
 // 正しい&lt;br /&gt;
 this.setSatate({comment:'Hello'});&lt;br /&gt;
&amp;amp;lt;blockquote&amp;amp;gt;this.stateを割り当てることができるのは、コンストラクタのみ&amp;amp;lt;/blockquote&amp;amp;gt;&lt;br /&gt;
=====stateは、非同期に更新される=====&lt;br /&gt;
*[[React]]は、複数のsetState() をパフォーマンスのためにまとめて一度に処理する。&lt;br /&gt;
*このため、this.propsとthis.stateは非同期に更新される&lt;br /&gt;
*これらの値を信頼して、次の状態への計算を行うべきではない&lt;br /&gt;
 // まちがい&lt;br /&gt;
 this.setState({&lt;br /&gt;
   counter: this.state.counter + this.props.increament,&lt;br /&gt;
 });&lt;br /&gt;
*修正するには、オブジェクトではなく関数を受け取る、setState()を使用する&lt;br /&gt;
*関数は、ひとつ前の状態(state)を最初の引数として、更新時のpropsを2つ目の引数として取る&lt;br /&gt;
 // 正しい&lt;br /&gt;
 this.setState((prevState, props) =&amp;amp;gt; ({&lt;br /&gt;
   counter: prevState.counter + prpos.increament&lt;br /&gt;
 }));&lt;br /&gt;
*通常の関数でもよい&lt;br /&gt;
 // 正しい&lt;br /&gt;
 this.setState(function(prevState, props) {&lt;br /&gt;
   return { counter: prevState.counter + props.increament };&lt;br /&gt;
 });&lt;br /&gt;
=====状態の更新はマージされる=====&lt;br /&gt;
*setState()を呼び出すと、[[React]]は、現在のstateに提供したオブジェクトをマージする&lt;br /&gt;
*例えば、いくつかの独立した変数を含む場合&lt;br /&gt;
 constructor(props) {&lt;br /&gt;
   super(props);&lt;br /&gt;
   this.state = {&lt;br /&gt;
     posts: []&lt;br /&gt;
     comments: []&lt;br /&gt;
   };&lt;br /&gt;
 }&lt;br /&gt;
*これらを別のsetState() で更新&lt;br /&gt;
 componentDidMount() {&lt;br /&gt;
   fetchPosts().then(response =&amp;amp;gt; { this.setState({ posts: response.posts }); });&lt;br /&gt;
   fetchComments().then(response =&amp;amp;gt; { this.setState({ commentss: response.comments }); });&lt;br /&gt;
 }&lt;br /&gt;
*マージはシャローなので、setState({comment}) は、this.state.posts を損なわずに、this.state.comments を置き換える&lt;br /&gt;
====データは下へ流れる====&lt;br /&gt;
*親だけでなく子コンポーネントも確実にステートフルかステートレスか知ることはできない。&lt;br /&gt;
*状態はしばしばローカルから呼び出されるかカプセル化されていて、他からアクセスできない。&lt;br /&gt;
*コンポーネントは、自身の状態をpropsを通して子コンポーネントに渡す&lt;br /&gt;
 &amp;amp;lt;h2&amp;amp;gt;It is {this.state.date.toLocalTimeString()}.&amp;amp;lt;/h2&amp;amp;gt;&lt;br /&gt;
*これは、ユーザー定義コンポーネントでも動作する&lt;br /&gt;
&amp;amp;lt;FormattedDate date={this.state.date} /&amp;amp;gt;&lt;br /&gt;
*FormattedDateコンポーネントは、propsにdateを受け取り、Clockの状態が何かは知らない。&lt;br /&gt;
 function FormatterDate(props) {&lt;br /&gt;
   return &amp;amp;lt;h2&amp;amp;gt;It is {props.date.toLocaleTimeString()}.&amp;amp;lt;/h2&amp;amp;gt;;&lt;br /&gt;
 }&lt;br /&gt;
*これは一般的に、トップダウン、もしくは、ユニディレクショナル データフローという&lt;br /&gt;
*状態は常に特定のコンポーネントに属する。&lt;br /&gt;
*データやUIは状態に由来し、ツリーのより下のコンポーネントにのみ影響を与えることができる&lt;br /&gt;
===イベントの処理===&lt;br /&gt;
*[[React]] 要素のイベント処理は、DOMでの処理ととても似ているが、いくつかシンタックスの差異がある。&lt;br /&gt;
**[[React]]イベントは、ロウアーケースではなく、キャメルケース&lt;br /&gt;
**JSXでは、stringではなく、関数をイベントハンドラーとして渡す。&lt;br /&gt;
&lt;br /&gt;
=====[[HTML]]=====&lt;br /&gt;
 &amp;amp;lt;button onclick=&amp;quot;test()&amp;quot; /&amp;amp;gt;&lt;br /&gt;
=====[[React]]=====&lt;br /&gt;
 &amp;amp;lt;button onClick={test} /&amp;amp;gt;&lt;br /&gt;
&lt;br /&gt;
*もう一つの違いは、[[React]]では、falseを返しデフォルトのふるまいを防止することができない。&lt;br /&gt;
*明示的に、preventDefault を呼び出す必要がある。&lt;br /&gt;
&lt;br /&gt;
=====[[HTML]]でデフォルトの新しいページを開くリンクのふるまいを防止する=====&lt;br /&gt;
 &amp;amp;lt;a href=&amp;quot;#&amp;quot; onclick=&amp;quot;console.log('hoge'); return false&amp;quot; &amp;amp;gt;Click&amp;amp;lt;/a&amp;amp;gt;&lt;br /&gt;
=====[[React]]=====&lt;br /&gt;
 function ActionLink() {&lt;br /&gt;
   function handleClick(e) {&lt;br /&gt;
     e.preventDefault();&lt;br /&gt;
     console.log('hoge');&lt;br /&gt;
   }&lt;br /&gt;
   return (&lt;br /&gt;
     &amp;amp;lt;a href=&amp;quot;#&amp;quot; onClick={handleClick} &amp;amp;gt;Click&amp;amp;lt;/a&amp;amp;gt;&lt;br /&gt;
   )&lt;br /&gt;
 } &lt;br /&gt;
*e は、本物ではないイベント。Reactでは、[https://www.w3.org/TR/DOM-Level-3-Events/ W3C]に合わせるために定義している。&lt;br /&gt;
*なので、ブラウザの互換性を心配する必要はない。[https://facebook.github.io/react/docs/events.html リファレンス]を参照&lt;br /&gt;
*[[React]]では、addEventListenerを通常呼び出す必要はない。要素が最初にレンダリングされるときに提供される&lt;br /&gt;
*ES6のクラスを使用するときの一般的なパターン、例えば、Toggle ボタン&lt;br /&gt;
 class Toggle extends [[React]].Component {&lt;br /&gt;
   constructor(props) {&lt;br /&gt;
     super(props);&lt;br /&gt;
     this.state = {isToggleOn: true};&lt;br /&gt;
     this.handleClick = this.handleClick.bind(this);&lt;br /&gt;
   }&lt;br /&gt;
   handleClick() {&lt;br /&gt;
     this.setState(prevStae =&amp;amp;gt; ({&lt;br /&gt;
       isToggleOn: !prevStae.isToggleOn&lt;br /&gt;
     }));&lt;br /&gt;
   }&lt;br /&gt;
   render() {&lt;br /&gt;
     return (&lt;br /&gt;
       &amp;amp;lt;button onClick={this.handleClick} &amp;amp;gt;&lt;br /&gt;
         {this.state.isToggleOn?&amp;quot;ON&amp;quot;:&amp;quot;OFF&amp;quot;}&lt;br /&gt;
       &amp;amp;lt;/button&amp;amp;gt;&lt;br /&gt;
     );&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
 [[React]]DOM.render(&lt;br /&gt;
   &amp;amp;lt;Toggle /&amp;amp;gt;,&lt;br /&gt;
   document.getElementById('root')&lt;br /&gt;
 );&lt;br /&gt;
*この文法の問題点は、LoggingButtonがレンダリングされるたびに、異なったコールバックが生成されること&lt;br /&gt;
*多くのケースで、これは問題ないが、このコールバックが下位のコンポーネントにpropとして渡される場合、コンポーネントは余分にレンダリングすることになる。&lt;br /&gt;
*コンストラクタでバインドするか、プロパティイニシャライザでバインドすることを推奨する。&lt;br /&gt;
===条件付きのレンダリング===&lt;br /&gt;
*[[React]]では、必要なら、振る舞いがカプセルかされた他と異なったコンポーネントを作成できる。&lt;br /&gt;
*Reactの条件付きレンダリングは、[[JavaScript]]の条件が動作するのと同じ方法で動作する。&lt;br /&gt;
*[[JavaScript]]のifのような演算子もしくは、条件演算子は、現在の状態を表した要素を作成するための、ReactがUIをそれに一致させることを許す。&lt;br /&gt;
=====以下の2つのコンポーネントについて考える=====&lt;br /&gt;
*ユーザーがログインしているか否かによって使い分けたい。&lt;br /&gt;
*isLoggedIn により、異なるレンダリングがなされる。&lt;br /&gt;
 function UserGreeting(props){&lt;br /&gt;
    return &amp;amp;lt;h1&amp;amp;gt;Welcome to back!&amp;amp;lt;/h1&amp;amp;gt;&lt;br /&gt;
 }    &lt;br /&gt;
 function GuestGreeting(props) {&lt;br /&gt;
    return &amp;amp;lt;h1&amp;amp;gt;Please Sign up!&amp;amp;lt;/h1&amp;amp;gt;&lt;br /&gt;
 }&lt;br /&gt;
 function Greeting(props) {&lt;br /&gt;
    const isLoggedIn = props.isLoggedIn;&lt;br /&gt;
    if (isLoggedIn) {&lt;br /&gt;
      return &amp;amp;lt;UserGreeting /&amp;amp;gt;&lt;br /&gt;
    } else {&lt;br /&gt;
      return &amp;amp;lt;GuestGreeting /&amp;amp;gt;&lt;br /&gt;
    }&lt;br /&gt;
 }    &lt;br /&gt;
 [[React]]DOM.render(&lt;br /&gt;
   &amp;amp;lt;Greeting isLoggedIn={true} /&amp;amp;gt;,&lt;br /&gt;
   document.getElementById('root')&lt;br /&gt;
 );&lt;br /&gt;
====要素変数====&lt;br /&gt;
*要素を保持するのに変数を利用できる。&lt;br /&gt;
*これは、出力結果が変わらない間に、条件によりコンポーネントの一部をレンダリングするのを助ける。&lt;br /&gt;
 function LoginButton(props) {&lt;br /&gt;
    return (&lt;br /&gt;
      &amp;amp;lt;button onClick={props.onClick} &amp;amp;gt;&lt;br /&gt;
        Login      &lt;br /&gt;
      &amp;amp;lt;/button&amp;amp;gt;&lt;br /&gt;
    );&lt;br /&gt;
 }&lt;br /&gt;
 function LogoutButton(props) {&lt;br /&gt;
    return (&lt;br /&gt;
      &amp;amp;lt;button onClick={props.onClick} &amp;amp;gt;&lt;br /&gt;
        Logout      &lt;br /&gt;
      &amp;amp;lt;/button&amp;amp;gt;&lt;br /&gt;
    );&lt;br /&gt;
 }&lt;br /&gt;
 class LoginControl extends [[React]].Component {&lt;br /&gt;
    constructor(props) {&lt;br /&gt;
      super(props);&lt;br /&gt;
      this.handleLoginClick = this.handleLoginClick.bind(this);&lt;br /&gt;
      this.handleLogoutClick = this.handleLogoutClick.bind(this);&lt;br /&gt;
      this.state = {isLoggedIn: false};&lt;br /&gt;
    }&lt;br /&gt;
    handleLoginClick() {&lt;br /&gt;
      this.setState({isLoggedIn: true});&lt;br /&gt;
    }&lt;br /&gt;
    handleLogoutClick(){&lt;br /&gt;
      this.setState({isLoggedIn: false});&lt;br /&gt;
    }&lt;br /&gt;
    render() {&lt;br /&gt;
      const isLoggedIn = this.state.isLoggedIn;&lt;br /&gt;
      let button = null;&lt;br /&gt;
      if (isLoggedIn) {&lt;br /&gt;
        button = &amp;amp;lt;LogoutButton onClick={this.handleLogoutClick} /&amp;amp;gt;&lt;br /&gt;
      } else {&lt;br /&gt;
        button = &amp;amp;lt;LoginButton onClick={this.handleLoginClick} /&amp;amp;gt;&lt;br /&gt;
      }&lt;br /&gt;
      return (&amp;amp;lt;div&amp;amp;gt;{button}&amp;amp;lt;/div&amp;amp;gt;);&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 [[React]]DOM.render(&lt;br /&gt;
   &amp;amp;lt;LoginControl /&amp;amp;gt;,&lt;br /&gt;
   document.getElementById('root')&lt;br /&gt;
 );&lt;br /&gt;
[[File:1085_react_debug.jpg]]&lt;br /&gt;
====インラインif と 論理 &amp;amp;&amp;amp; 演算子====&lt;br /&gt;
*true &amp;amp;&amp;amp; 演算子の場合評価され、false &amp;amp;&amp;amp; の場合、falseとなり[[React]]は無視する&lt;br /&gt;
 function MailBox(props) {&lt;br /&gt;
    const unreadMessages = props.unreadMessages;&lt;br /&gt;
    return  (&lt;br /&gt;
      &amp;amp;lt;div&amp;amp;gt;&lt;br /&gt;
        &amp;amp;lt;h1&amp;amp;gt;Hello!&amp;amp;lt;/h1&amp;amp;gt;&lt;br /&gt;
        {unreadMessages.length &amp;amp;gt; 0 &amp;amp;&amp;amp;&lt;br /&gt;
          &amp;amp;lt;h2&amp;amp;gt;&lt;br /&gt;
            You have {unreadMessages.length} unread messages.&lt;br /&gt;
          &amp;amp;lt;/h2&amp;amp;gt;&lt;br /&gt;
        }&lt;br /&gt;
      &amp;amp;lt;/div&amp;amp;gt;&lt;br /&gt;
    );&lt;br /&gt;
 }&lt;br /&gt;
 const messages = ['message1','message2'];&lt;br /&gt;
 [[React]]DOM.render(&lt;br /&gt;
   &amp;amp;lt;MailBox unreadMessages={messages} /&amp;amp;gt;,&lt;br /&gt;
   document.getElementById('root')&lt;br /&gt;
 );&lt;br /&gt;
====インライン if-else とコンディション演算子====&lt;br /&gt;
*条件 ? true : false&lt;br /&gt;
 function UserGreeting(props){&lt;br /&gt;
     return &amp;amp;lt;h1&amp;amp;gt;Welcome to back!&amp;amp;lt;/h1&amp;amp;gt;&lt;br /&gt;
 }    &lt;br /&gt;
 function GuestGreeting(props) {&lt;br /&gt;
     return &amp;amp;lt;h1&amp;amp;gt;Please Sign up!&amp;amp;lt;/h1&amp;amp;gt;&lt;br /&gt;
 }&lt;br /&gt;
 function Greeting(props) {&lt;br /&gt;
     const isLoggedIn = props.isLoggedIn;&lt;br /&gt;
     return (&lt;br /&gt;
       &amp;amp;lt;div&amp;amp;gt;&lt;br /&gt;
       {isLoggedIn ? (&lt;br /&gt;
           &amp;amp;lt;UserGreeting /&amp;amp;gt;&lt;br /&gt;
         ) : (&lt;br /&gt;
           &amp;amp;lt;GuestGreeting /&amp;amp;gt;&lt;br /&gt;
         )&lt;br /&gt;
       }&lt;br /&gt;
       &amp;amp;lt;/div&amp;amp;gt;&lt;br /&gt;
     );&lt;br /&gt;
 }    &lt;br /&gt;
 [[React]]DOM.render(&lt;br /&gt;
   &amp;amp;lt;Greeting isLoggedIn={false} /&amp;amp;gt;,&lt;br /&gt;
   document.getElementById('root')&lt;br /&gt;
 );&lt;br /&gt;
====コンポーネントのレンダリングさせない====&lt;br /&gt;
*他のコンポーネントからレンダリングされたとしてもコンポーネントを隠したい場合、render出力の代わりにnullを返す&lt;br /&gt;
 function WarningBanner(props){&lt;br /&gt;
   if(!props.warn) {&lt;br /&gt;
     return null;&lt;br /&gt;
   }&lt;br /&gt;
   return (&lt;br /&gt;
     &amp;amp;lt;div&amp;amp;gt;Warning!&amp;amp;lt;/div&amp;amp;gt;&lt;br /&gt;
   );&lt;br /&gt;
 }&lt;br /&gt;
 class Page extends [[React]].Component {&lt;br /&gt;
   constructor(props) {&lt;br /&gt;
     super(props);&lt;br /&gt;
     this.state = {showWarning : true}&lt;br /&gt;
     this.handleToggleClick = this.handleToggleClick.bind(this);&lt;br /&gt;
   }&lt;br /&gt;
   handleToggleClick() {&lt;br /&gt;
     this.setState(prevState =&amp;amp;gt;({showWarning : !prevState.showWarning}));&lt;br /&gt;
   }&lt;br /&gt;
   render() {&lt;br /&gt;
     return (&lt;br /&gt;
       &amp;amp;lt;div&amp;amp;gt;&lt;br /&gt;
         &amp;amp;lt;WarningBanner warn={this.state.showWarning} /&amp;amp;gt;&lt;br /&gt;
         &amp;amp;lt;button onClick={this.handleToggleClick}&amp;amp;gt;&lt;br /&gt;
           {this.state.showWarning ? 'Hide' : 'Show'}&lt;br /&gt;
         &amp;amp;lt;/button&amp;amp;gt;&lt;br /&gt;
       &amp;amp;lt;/div&amp;amp;gt;&lt;br /&gt;
     );&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 [[React]]DOM.render(&lt;br /&gt;
   &amp;amp;lt;Page /&amp;amp;gt;,&lt;br /&gt;
   document.getElementById('root')&lt;br /&gt;
 );&lt;br /&gt;
[[File:1095_react10.jpg]]&lt;br /&gt;
===リストとキー===&lt;br /&gt;
=====[[JavaScript]]でリストの変換には、map()を利用する=====&lt;br /&gt;
 const numbers = [1,2,3,4,5];&lt;br /&gt;
 const doubled = numbers.map((number)=&amp;amp;gt; number * 2);&lt;br /&gt;
 console.log(doubled)&lt;br /&gt;
 &amp;amp;gt; [2, 4, 6, 8, 10]&lt;br /&gt;
*[[React]] では同様に配列をリストに変換する&lt;br /&gt;
====複数のコンポーネントをレンダリングする====&lt;br /&gt;
 const fruits = ['apple','orange','grape','banana'];&lt;br /&gt;
 const listItems = fruits.map((fruit) =&amp;amp;gt; &amp;amp;lt;li&amp;amp;gt;{fruit}&amp;amp;lt;/li&amp;amp;gt;);&lt;br /&gt;
 [[React]]DOM.render(&lt;br /&gt;
   &amp;amp;lt;ol&amp;amp;gt;{listItems}&amp;amp;lt;/ol&amp;amp;gt;,&lt;br /&gt;
   document.getElementById('root')&lt;br /&gt;
 );&lt;br /&gt;
&lt;br /&gt;
[[File:1096_react11.jpg]]&lt;br /&gt;
====基本的なリストコンポーネント====&lt;br /&gt;
*通常リストはコンポーネントに含まれる&lt;br /&gt;
=====Keys=====&lt;br /&gt;
*keyを指定しないと警告がでる&lt;br /&gt;
*keyは、[[React]]が、どのアイテムが登録、変更、削除されたのか特定するのに役立つ&lt;br /&gt;
*文字列で兄弟間でユニークな値を設定するのが望ましい&lt;br /&gt;
 function FruitList(props) {&lt;br /&gt;
   const fruits = props.fruits;&lt;br /&gt;
   const listItems = fruits.map((fruit) =&amp;amp;gt; &amp;amp;lt;li key={fruit}&amp;amp;gt;{fruit}&amp;amp;lt;/li&amp;amp;gt;);&lt;br /&gt;
   return (&lt;br /&gt;
     &amp;amp;lt;ol&amp;amp;gt;{listItems}&amp;amp;lt;/ol&amp;amp;gt; &lt;br /&gt;
   );&lt;br /&gt;
 } &lt;br /&gt;
 const fruits = ['apple','orange','grape','banana'];&lt;br /&gt;
 [[React]]DOM.render(&lt;br /&gt;
   &amp;amp;lt;FruitList fruits={fruits}/&amp;amp;gt;,&lt;br /&gt;
   document.getElementById('root')&lt;br /&gt;
 );&lt;br /&gt;
====コンポーネントをKeyと取り出す====&lt;br /&gt;
*Keyが意味を持つのは、配列を囲むコンテキストにおいて&lt;br /&gt;
*兄弟間で同じKeyを持つとエラーとなる&lt;br /&gt;
 function ListItem(props) {&lt;br /&gt;
   // この&amp;amp;lt;li&amp;amp;gt; にKeyを設定するのは、ここがルートになるため間違い&lt;br /&gt;
   return &amp;amp;lt;li&amp;amp;gt;{props.value}&amp;amp;lt;/li&amp;amp;gt;&lt;br /&gt;
 }&lt;br /&gt;
 function FruitList(props) {&lt;br /&gt;
   const fruits = props.fruits;&lt;br /&gt;
   // &amp;amp;lt;ListItem&amp;amp;gt;の配列となるため、ここでKeyを指定するのが正しい&lt;br /&gt;
   const listItems = fruits.map((fruit) =&amp;amp;gt; &amp;amp;lt;ListItem key={fruit} value={fruit} /&amp;amp;gt;);&lt;br /&gt;
   return (&lt;br /&gt;
     &amp;amp;lt;ol&amp;amp;gt;{listItems}&amp;amp;lt;/ol&amp;amp;gt; &lt;br /&gt;
   );&lt;br /&gt;
 } &lt;br /&gt;
 const fruits = ['apple','orange','grape','banana'];&lt;br /&gt;
 [[React]]DOM.render(&lt;br /&gt;
   &amp;amp;lt;FruitList fruits={fruits}/&amp;amp;gt;,&lt;br /&gt;
   document.getElementById('root')&lt;br /&gt;
 );&lt;br /&gt;
====JSXでmap()を埋め込む====&lt;br /&gt;
*中括弧のインラインにmap()を置くことができる&lt;br /&gt;
 function ListItem(props) {&lt;br /&gt;
   return &amp;amp;lt;li&amp;amp;gt;{props.value}&amp;amp;lt;/li&amp;amp;gt;&lt;br /&gt;
 }&lt;br /&gt;
 function FruitList(props) {&lt;br /&gt;
   const fruits = props.fruits;&lt;br /&gt;
   return (&lt;br /&gt;
     &amp;amp;lt;ol&amp;amp;gt;{fruits.map((fruit) =&amp;amp;gt; &amp;amp;lt;ListItem key={fruit} value={fruit} /&amp;amp;gt;)}&amp;amp;lt;/ol&amp;amp;gt; &lt;br /&gt;
   );&lt;br /&gt;
&lt;br /&gt;
 } &lt;br /&gt;
 const fruits = ['apple','orange','grape','banana'];&lt;br /&gt;
 [[React]]DOM.render(&lt;br /&gt;
   &amp;amp;lt;FruitList fruits={fruits}/&amp;amp;gt;,&lt;br /&gt;
   document.getElementById('root')&lt;br /&gt;
 );&lt;br /&gt;
===Form===&lt;br /&gt;
*HTML Formは、[[React]]では、少し他のDOMとは動作が異なる。&lt;br /&gt;
*なぜなら Fromは通常内部状態をもつから。&lt;br /&gt;
====コントロールされたコンポーネント====&lt;br /&gt;
*[[HTML]]でFormは、自身の状態を維持しユーザー入力に基づいて状態を更新する。&lt;br /&gt;
*[[React]]では、変化可能な状態はコンポーネントのstateプロパティに保持し、setState()からのみ更新される。&lt;br /&gt;
*&amp;quot;single source of truth&amp;quot;として[[React]] stateを作成することにより2つを結びつけることができる。&lt;br /&gt;
*[[React]]コンポーネントはFormまたコントロールでユーザー入力により、何が起きたかを描画する。&lt;br /&gt;
*input Form 要素の値は、[[React]]によりこの方法で制御される。&lt;br /&gt;
*これは、「コントロールされたコンポーネント」と呼ばれる。&lt;br /&gt;
&lt;br /&gt;
 class NameForm extends [[React]].Component {&lt;br /&gt;
   constructor(props) {&lt;br /&gt;
     super(props);&lt;br /&gt;
     this.state = {value : ''};&lt;br /&gt;
     this.handleChange = this.handleChange.bind(this);&lt;br /&gt;
     this.handleSubmit = this.handleSubmit.bind(this);&lt;br /&gt;
   }&lt;br /&gt;
   handleChange(event) {&lt;br /&gt;
     this.setState({value : event.target.value });&lt;br /&gt;
   }&lt;br /&gt;
   handleSubmit(event) {&lt;br /&gt;
     alert('A name was submitted ' + this.state.value);&lt;br /&gt;
     event.preventDefault();&lt;br /&gt;
   }&lt;br /&gt;
   render() {&lt;br /&gt;
     return(&lt;br /&gt;
       &amp;amp;lt;form onSubmit={this.handleSubmit}&amp;amp;gt;&lt;br /&gt;
          &amp;amp;lt;label&amp;amp;gt;Name: &amp;amp;lt;input type=&amp;quot;text&amp;quot; value={this.state.value} onChange={this.handleChange} /&amp;amp;gt;&amp;amp;lt;/label&amp;amp;gt;&lt;br /&gt;
          &amp;amp;lt;input type=&amp;quot;submit&amp;quot; value=&amp;quot;Submit&amp;quot;/&amp;amp;gt;&lt;br /&gt;
       &amp;amp;lt;/form&amp;amp;gt;&lt;br /&gt;
     );&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
 [[React]]DOM.render(&lt;br /&gt;
   &amp;amp;lt;NameForm /&amp;amp;gt;,&lt;br /&gt;
   document.getElementById('root')&lt;br /&gt;
 );&lt;br /&gt;
[[File:1097_react12.jpg]]&lt;br /&gt;
*valueが、Form要素に設定されると、表示されるvalueは、常にthis.state.valueとなる&lt;br /&gt;
*すべてのキーストロークで、handleChangeが起動し、[[React]]のstateを更新する&lt;br /&gt;
*表示されるvalueも更新される&lt;br /&gt;
 handleChange(event) {&lt;br /&gt;
   this.setState({value : event.target.value.toUpperCase() });&lt;br /&gt;
 }&lt;br /&gt;
====textarea/select タグ====&lt;br /&gt;
 class SelectParts extends [[React]].Component {&lt;br /&gt;
   constructor(props){&lt;br /&gt;
     super(props);&lt;br /&gt;
     this.state = {value: 'coconuts'};&lt;br /&gt;
     this.handleChange = this.handleChange.bind(this);&lt;br /&gt;
   }&lt;br /&gt;
   handleChange(event) {&lt;br /&gt;
     this.setState({value: event.target.value});&lt;br /&gt;
   }&lt;br /&gt;
   render(){&lt;br /&gt;
     return(&lt;br /&gt;
       &amp;amp;lt;label&amp;amp;gt;Select:&lt;br /&gt;
         &amp;amp;lt;select value={this.state.value} onChange={this.handleChange}&amp;amp;gt;&lt;br /&gt;
           &amp;amp;lt;option value=&amp;quot;grapefruit&amp;quot;&amp;amp;gt;Grape Fruit&amp;amp;lt;/option&amp;amp;gt;&lt;br /&gt;
           &amp;amp;lt;option value=&amp;quot;lime&amp;quot;&amp;amp;gt;Lime&amp;amp;lt;/option&amp;amp;gt;&lt;br /&gt;
           &amp;amp;lt;option value=&amp;quot;coconuts&amp;quot;&amp;amp;gt;Coconuts&amp;amp;lt;/option&amp;amp;gt;&lt;br /&gt;
           &amp;amp;lt;option value=&amp;quot;mango&amp;quot;&amp;amp;gt;Mango&amp;amp;lt;/option&amp;amp;gt;&lt;br /&gt;
         &amp;amp;lt;/select&amp;amp;gt;&lt;br /&gt;
       &amp;amp;lt;/label&amp;amp;gt;&lt;br /&gt;
     );&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
 class TextareaParts extends [[React]].Component {&lt;br /&gt;
   constructor(props){&lt;br /&gt;
     super(props);&lt;br /&gt;
     this.state = {&lt;br /&gt;
       value : 'なにか書いて'&lt;br /&gt;
     };&lt;br /&gt;
     this.handleChange = this.handleChange.bind(this);&lt;br /&gt;
   }&lt;br /&gt;
   handleChange(event) {&lt;br /&gt;
     this.setState({value : event.target.value});&lt;br /&gt;
   }&lt;br /&gt;
   render(){&lt;br /&gt;
     return (&lt;br /&gt;
         &amp;amp;lt;label&amp;amp;gt;Textarea:&amp;amp;lt;textarea value={this.state.value} onChange={this.handleChange} /&amp;amp;gt;&amp;amp;lt;/label&amp;amp;gt;&lt;br /&gt;
     );&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
 [[React]]DOM.render(&lt;br /&gt;
   &amp;amp;lt;div&amp;amp;gt;&lt;br /&gt;
     &amp;amp;lt;SelectParts /&amp;amp;gt;&lt;br /&gt;
     &amp;amp;lt;TextareaParts /&amp;amp;gt;&lt;br /&gt;
   &amp;amp;lt;/div&amp;amp;gt;,&lt;br /&gt;
   document.getElementById('root')&lt;br /&gt;
 );&lt;br /&gt;
====複数入力項目の処理====&lt;br /&gt;
*複数のコントロールされた入力要素を処理したい場合、name属性を各要素に追加する&lt;br /&gt;
*ハンドラー関数で、event.target.name の値に基づいて、どの要素か判定&lt;br /&gt;
*ES6 [https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Operators/Object_initializer#Computed_property_names 計算されたプロパティ名]構文をkey状態を更新するのに使用&lt;br /&gt;
 class Reservation extends [[React]].Component {&lt;br /&gt;
   constructor(props) {&lt;br /&gt;
     super(props);&lt;br /&gt;
     this.state = {&lt;br /&gt;
       isGoing: true,&lt;br /&gt;
       numberOfGuests: 2&lt;br /&gt;
     };&lt;br /&gt;
     this.handleInputChange = this.handleInputChange.bind(this);&lt;br /&gt;
   }&lt;br /&gt;
   handleInputChange(event) {&lt;br /&gt;
     const target = event.target;&lt;br /&gt;
     const value = (target.type == 'checkbox') ? target.checked : target.value;&lt;br /&gt;
     const name = target.name;&lt;br /&gt;
     this.setState({[name]: value});&lt;br /&gt;
   }&lt;br /&gt;
   render(){&lt;br /&gt;
     return (&lt;br /&gt;
       &amp;amp;lt;form&amp;amp;gt;&lt;br /&gt;
         &amp;amp;lt;label&amp;amp;gt;Is going:&amp;amp;lt;input name=&amp;quot;isGoing&amp;quot; type=&amp;quot;checkbox&amp;quot; checked={this.state.isGoing} onChange={this.handleInputChange}/&amp;amp;gt;&amp;amp;lt;/label&amp;amp;gt;&lt;br /&gt;
         &amp;amp;lt;br /&amp;amp;gt;&lt;br /&gt;
         &amp;amp;lt;label&amp;amp;gt;Number of guests:&amp;amp;lt;input name=&amp;quot;numberOfGuests&amp;quot; type=&amp;quot;number&amp;quot; value={this.state.numberOfGuests} onChange={this.handleInputChange}/&amp;amp;gt;&amp;amp;lt;/label&amp;amp;gt;&lt;br /&gt;
       &amp;amp;lt;/form&amp;amp;gt;&lt;br /&gt;
     );&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
 [[React]]DOM.render(&lt;br /&gt;
   &amp;amp;lt;div&amp;amp;gt;&lt;br /&gt;
     &amp;amp;lt;[[R]]eservation /&amp;amp;gt;&lt;br /&gt;
   &amp;amp;lt;/div&amp;amp;gt;,&lt;br /&gt;
   document.getElementById('root')&lt;br /&gt;
 );&lt;br /&gt;
[[File:1098_react13.jpg]]&lt;br /&gt;
====コントロールされたコンポーネント以外の方法====&lt;br /&gt;
*コントロールされたコンポーネントを利用するのが、冗長な場合がある。&lt;br /&gt;
*入力フォームを実装するための、[https://facebook.github.io/react/docs/uncontrolled-components.html コントロールされないコンポーネント]を参照。&lt;br /&gt;
===状態を持ち上げる===&lt;br /&gt;
*いくつかのコンポーネントは同じ変更をデータに反映させることを必要とする。&lt;br /&gt;
*共有状態をそれらの、最も近い共通の祖先に持ち上げることを推奨する。&lt;br /&gt;
=====水が沸騰しているかどうかの計算を行う。=====&lt;br /&gt;
 function BoilingVerdict(props) {&lt;br /&gt;
   if (props.celsius &amp;amp;gt;= 100) {&lt;br /&gt;
     return &amp;amp;lt;p&amp;amp;gt;The water would boil.&amp;amp;lt;/p&amp;amp;gt;;&lt;br /&gt;
   }&lt;br /&gt;
   return &amp;amp;lt;p&amp;amp;gt;The water would not boil.&amp;amp;lt;/p&amp;amp;gt;&lt;br /&gt;
 }&lt;br /&gt;
 class Calculator extends [[React]].Component {&lt;br /&gt;
   constructor(props) {&lt;br /&gt;
     super(props);&lt;br /&gt;
     this.handleChange = this.handleChange.bind(this);&lt;br /&gt;
     this.state = {temprature: ''};&lt;br /&gt;
   }&lt;br /&gt;
   handleChange(e){&lt;br /&gt;
     this.setState({temprature: e.target.value});&lt;br /&gt;
   }&lt;br /&gt;
   render(){&lt;br /&gt;
     const temprature = this.state.temprature;&lt;br /&gt;
     return (&lt;br /&gt;
       &amp;amp;lt;fieldset&amp;amp;gt;&lt;br /&gt;
         &amp;amp;lt;legend&amp;amp;gt;Enter temprature in Celsius:&amp;amp;lt;/legend&amp;amp;gt;&lt;br /&gt;
         &amp;amp;lt;input value={temprature} onChange={this.handleChange} /&amp;amp;gt;&lt;br /&gt;
         &amp;amp;lt;BoilingVerdict celsius={parseFloat(temprature)} /&amp;amp;gt;  &lt;br /&gt;
       &amp;amp;lt;/fieldset&amp;amp;gt;&lt;br /&gt;
     );&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
 [[React]]DOM.render(&lt;br /&gt;
   &amp;amp;lt;div&amp;amp;gt;&lt;br /&gt;
     &amp;amp;lt;Calculator /&amp;amp;gt;&lt;br /&gt;
   &amp;amp;lt;/div&amp;amp;gt;,&lt;br /&gt;
   document.getElementById('root')&lt;br /&gt;
 );&lt;br /&gt;
[[File:1099_react14.jpg]]&lt;br /&gt;
====2つ目の入力を追加する====&lt;br /&gt;
*華氏の入力を追加し同期させる&lt;br /&gt;
*[[React]]でstateを共有するには、共通の祖先に移動させることで実現でき、「状態の持ち上げ」という&lt;br /&gt;
*TempratureInputのローカルstateをCalcuratorへ移動させる&lt;br /&gt;
*Calucratorの共有stateは、「真の情報源」となる&lt;br /&gt;
*TempratureInputにとって、tempuratureがローカルの場合、propsは読み取り専用となるので、this.setState()とするしかないが、tempratureが、親のpropsなので、管理する必要はなくなる。&lt;br /&gt;
 const scaleName = {&lt;br /&gt;
   c: '摂氏',&lt;br /&gt;
   f: '華氏'&lt;br /&gt;
 };&lt;br /&gt;
 function BoilingVerdict(props) {&lt;br /&gt;
   if (props.celsius &amp;amp;gt;= 100) {&lt;br /&gt;
     return &amp;amp;lt;p&amp;amp;gt;The water would boil.&amp;amp;lt;/p&amp;amp;gt;;&lt;br /&gt;
   }&lt;br /&gt;
   return &amp;amp;lt;p&amp;amp;gt;The water would not boil.&amp;amp;lt;/p&amp;amp;gt;&lt;br /&gt;
 }&lt;br /&gt;
 function toCelsius(fahrenheit) {&lt;br /&gt;
   return (fahrenheit - 32) * 5/9;&lt;br /&gt;
 }&lt;br /&gt;
 function toFahrenheit(celsius) {&lt;br /&gt;
   return (celsius * 9/5) + 32;&lt;br /&gt;
 }&lt;br /&gt;
 function tryConvert(temprature, convert) {&lt;br /&gt;
   const input = parseFloat(temprature);&lt;br /&gt;
   if (Number.isNaN(input)) {&lt;br /&gt;
     return '';&lt;br /&gt;
   }&lt;br /&gt;
   const output = convert(input);&lt;br /&gt;
   const rounded = Math.round(output * 1000) / 1000;&lt;br /&gt;
   return rounded.toString();&lt;br /&gt;
 }&lt;br /&gt;
 class TempratureInput extends [[React]].Component {&lt;br /&gt;
   constructor(props) {&lt;br /&gt;
     super(props);&lt;br /&gt;
     this.handleChange = this.handleChange.bind(this);&lt;br /&gt;
     this.state = {temprature: ''};&lt;br /&gt;
   }&lt;br /&gt;
   handleChange(e){&lt;br /&gt;
     // before:this.setState({temprature: e.target.value});&lt;br /&gt;
     this.props.onTempratureChange(e.target.value);&lt;br /&gt;
   }&lt;br /&gt;
   render(){&lt;br /&gt;
     // before:const temprature = this.state.temprature;&lt;br /&gt;
     const temprature = this.props.temprature;&lt;br /&gt;
     const scale = this.props.scale;&lt;br /&gt;
     return (&lt;br /&gt;
       &amp;amp;lt;fieldset&amp;amp;gt;&lt;br /&gt;
         &amp;amp;lt;legend&amp;amp;gt;Enter temprature in {scaleName[scale]}:&amp;amp;lt;/legend&amp;amp;gt;&lt;br /&gt;
         &amp;amp;lt;input value={temprature} onChange={this.handleChange} /&amp;amp;gt;&lt;br /&gt;
         &amp;amp;lt;BoilingVerdict celsius={parseFloat(temprature)} /&amp;amp;gt;  &lt;br /&gt;
       &amp;amp;lt;/fieldset&amp;amp;gt;&lt;br /&gt;
     );&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
 class Calculator extends [[React]].Component {&lt;br /&gt;
   constructor(props) {&lt;br /&gt;
     super(props);&lt;br /&gt;
     this.handleCelsiumChange = this.handleCelsiumChange.bind(this);&lt;br /&gt;
     this.handlFahrenheitChange = this.handlFahrenheitChange.bind(this);&lt;br /&gt;
     this.state = {scale:'c', temprature:''};&lt;br /&gt;
   }&lt;br /&gt;
   handleCelsiumChange(temprature) {&lt;br /&gt;
     this.setState({scale:'c', temprature});&lt;br /&gt;
   }&lt;br /&gt;
   handlFahrenheitChange(temprature) {&lt;br /&gt;
     this.setState({scale:'f', temprature});&lt;br /&gt;
   }&lt;br /&gt;
   render() {&lt;br /&gt;
     const scale = this.state.scale;&lt;br /&gt;
     const temprature = this.state.temprature;&lt;br /&gt;
     const celsius = scale == 'f' ? tryConvert(temprature, toCelsius) : temprature;&lt;br /&gt;
     const fahrenheit = scale == 'c' ? tryConvert(temprature, toFahrenheit) : temprature;&lt;br /&gt;
     return (&lt;br /&gt;
       &amp;amp;lt;div&amp;amp;gt;&lt;br /&gt;
         &amp;amp;lt;TempratureInput scale=&amp;quot;c&amp;quot; temprature={celsius} onTempratureChange={this.handleCelsiumChange} /&amp;amp;gt;&lt;br /&gt;
         &amp;amp;lt;TempratureInput scale=&amp;quot;f&amp;quot; temprature={fahrenheit} onTempratureChange={this.handlFahrenheitChange}/&amp;amp;gt;&lt;br /&gt;
         &amp;amp;lt;BoilingVerdict celsius={parseFloat(celsius)} /&amp;amp;gt;&lt;br /&gt;
       &amp;amp;lt;/div&amp;amp;gt;&lt;br /&gt;
     );&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
 [[React]]DOM.render(&lt;br /&gt;
   &amp;amp;lt;div&amp;amp;gt;&lt;br /&gt;
     &amp;amp;lt;Calculator /&amp;amp;gt;&lt;br /&gt;
   &amp;amp;lt;/div&amp;amp;gt;,&lt;br /&gt;
   document.getElementById('root')&lt;br /&gt;
 );&lt;br /&gt;
[[File:1100_react15.jpg]]&lt;br /&gt;
===コンポジションと継承===&lt;br /&gt;
*[[React]]は強力なコンポジションモデルをもつ。コンポーネントの再利用には継承よりコンポジションを推奨する&lt;br /&gt;
====封じ込める====&lt;br /&gt;
*一部のコンポーネントは自身の子供を事前に知ることができない&lt;br /&gt;
*これは、特にサイドバーやダイアログなどボックスを表現するコンポーネント共通&lt;br /&gt;
*このようなコンポーネントには特別な子供propを使用し直接その要素に出力する&lt;br /&gt;
*&amp;amp;lt;FancyBorder&amp;amp;gt;の内側に何があっても、JSXタグはFancyBorderコンポーネントをprops.children として経由する&lt;br /&gt;
 &amp;amp;lt;style type=&amp;quot;text/css&amp;quot;&amp;amp;gt;&lt;br /&gt;
   div.FancyBorder {&lt;br /&gt;
     border : 2px dashed;&lt;br /&gt;
   }&lt;br /&gt;
   div.FancyBorder-blue {&lt;br /&gt;
     border-color: blue;&lt;br /&gt;
   }&lt;br /&gt;
 &amp;amp;lt;/style&amp;amp;gt;&lt;br /&gt;
&lt;br /&gt;
 function FancyBorder(props) {&lt;br /&gt;
   return (&lt;br /&gt;
     &amp;amp;lt;div className={'FancyBorder FancyBorder-' + props.color}&amp;amp;gt;&lt;br /&gt;
       {props.children}&lt;br /&gt;
     &amp;amp;lt;/div&amp;amp;gt;&lt;br /&gt;
   );&lt;br /&gt;
 }&lt;br /&gt;
 function WelcomDialog() {&lt;br /&gt;
   return (&lt;br /&gt;
     &amp;amp;lt;FancyBorder color=&amp;quot;blue&amp;quot;&amp;amp;gt;&lt;br /&gt;
       &amp;amp;lt;h1 className=&amp;quot;Dialog-title&amp;quot;&amp;amp;gt;Welcome&amp;amp;lt;/h1&amp;amp;gt;&lt;br /&gt;
     &amp;amp;lt;/FancyBorder&amp;amp;gt;&lt;br /&gt;
   );&lt;br /&gt;
 }&lt;br /&gt;
 [[React]]DOM.render(&lt;br /&gt;
   &amp;amp;lt;div&amp;amp;gt;&lt;br /&gt;
     &amp;amp;lt;WelcomDialog /&amp;amp;gt;&lt;br /&gt;
   &amp;amp;lt;/div&amp;amp;gt;,&lt;br /&gt;
   document.getElementById('root')&lt;br /&gt;
 );&lt;br /&gt;
[[File:1101_react16.jpg]]&lt;br /&gt;
====特殊化====&lt;br /&gt;
*コンポーネントを他のコンポーネントの特殊なものとして考えることがある、例えば、WelcomDialogはDialogの特殊な例として。&lt;br /&gt;
*[[React]]では、コンポジションを使って実現する&lt;br /&gt;
*クラスを用いても同様に記述できる&lt;br /&gt;
 function Dialog(props) {&lt;br /&gt;
   return (&lt;br /&gt;
     &amp;amp;lt;FancyBorder color=&amp;quot;blue&amp;quot;&amp;amp;gt;&lt;br /&gt;
       &amp;amp;lt;h1 className=&amp;quot;Dialog-title&amp;quot;&amp;amp;gt;{props.title}&amp;amp;lt;/h1&amp;amp;gt;&lt;br /&gt;
     &amp;amp;lt;/FancyBorder&amp;amp;gt;&lt;br /&gt;
   );&lt;br /&gt;
 }&lt;br /&gt;
 function FancyBorder(props) {&lt;br /&gt;
   return (&lt;br /&gt;
     &amp;amp;lt;div className={'FancyBorder FancyBorder-' + props.color}&amp;amp;gt;&lt;br /&gt;
       {props.children}&lt;br /&gt;
     &amp;amp;lt;/div&amp;amp;gt;&lt;br /&gt;
   );&lt;br /&gt;
 }&lt;br /&gt;
 function WelcomDialog() {&lt;br /&gt;
   return (&lt;br /&gt;
     &amp;amp;lt;Dialog title=&amp;quot;Welcome&amp;quot; /&amp;amp;gt;&lt;br /&gt;
   );&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
===[[React Router]]===&lt;br /&gt;
*[[React Router]]&lt;br /&gt;
===[[Redux]]===&lt;br /&gt;
*[[Redux]]&lt;br /&gt;
===[[Tips]]===&lt;br /&gt;
*[http://typea.info/blg/glob/2017/06/react.html React のシンタックスエラーをデバッグ]&lt;br /&gt;
&lt;br /&gt;
{{ref example.zip}}&lt;br /&gt;
====ビルド====&lt;br /&gt;
*https://mae.chab.in/archives/2765&lt;br /&gt;
*https://mae.chab.in/archives/2891&lt;/div&gt;</summary>
		<author><name>Piroto</name></author>
		
	</entry>
	<entry>
		<id>https://www.typea.info/tips_/index.php?title=React&amp;diff=35330</id>
		<title>React</title>
		<link rel="alternate" type="text/html" href="https://www.typea.info/tips_/index.php?title=React&amp;diff=35330"/>
		<updated>2024-10-05T08:39:06Z</updated>

		<summary type="html">&lt;p&gt;Piroto: /* ファイル拡張子 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==[[React]]==&lt;br /&gt;
[[Node.js]] | [[Next.js]] |&lt;br /&gt;
&lt;br /&gt;
{{amazon|4873117887}}&lt;br /&gt;
&lt;br /&gt;
{{amazon|4815619484}}&lt;br /&gt;
&lt;br /&gt;
===スケルトン作成===&lt;br /&gt;
#[https://www.typea.info/blog/index.php/2017/08/15/react_1/ 開発の全体像を把握しつつ開発環境を整える]&lt;br /&gt;
#[https://www.typea.info/blog/index.php/2017/08/16/react_router/ React の単純なサンプルに React Router を適用する]&lt;br /&gt;
#[https://www.typea.info/blog/index.php/2017/08/17/react_react_router_redux-saga/ React の単純なサンプルに React Router を組み込んだものに Redux-Saga を適用する]&lt;br /&gt;
#[https://www.typea.info/blog/index.php/2017/08/19/react_react_router_redux-saga_ajax/ React の単純なサンプルに React Router を組み込んだものに Redux-Saga を適用したものからAjax通信を組み込む]&lt;br /&gt;
#[https://www.typea.info/blog/index.php/2017/08/23/react-react_router-redux-saga-superagent_bootstrap/ React環境-&amp;amp;gt;React Router-&amp;amp;gt;Redux-Saga-&amp;amp;gt;SuperAgent に Bootstrapを適用する]&lt;br /&gt;
&lt;br /&gt;
==導入==&lt;br /&gt;
&lt;br /&gt;
===Create React App===&lt;br /&gt;
*Reactアプリ開発のためのコマンドラインツール。トランスパイラ、バンドラ、開発サーバーなどを含むツールチェーン&lt;br /&gt;
*Facebook本家が提供。他にもNext.js、Vite、Gatsby、Parcelなどのツールチェーンがある。&lt;br /&gt;
*より高度な環境としてNext.jsも存在&lt;br /&gt;
&lt;br /&gt;
===Next.js===&lt;br /&gt;
*[[Next.js]]&lt;br /&gt;
*Reactは、あくまでUI部分のみ&lt;br /&gt;
*本格的なアプリ開発には周辺領域を担うためのフレームワークが必要&lt;br /&gt;
*Reactベースのフレームワークとしてデファクトスタンダードと言える存在&lt;br /&gt;
*主なライブラリ&lt;br /&gt;
**ファイルシステムベースの設定レスルーター&lt;br /&gt;
**サーバーコンポーネント&lt;br /&gt;
**データ取得用fetchメソッド&lt;br /&gt;
**リソース組み込みの自動最適化&lt;br /&gt;
**CSSフレームワーク、Tailwind　CSSへの標準対応&lt;br /&gt;
&lt;br /&gt;
===Node===&lt;br /&gt;
[[Node.js]] のインストール&lt;br /&gt;
&lt;br /&gt;
====npx====&lt;br /&gt;
*ローカルにインストールされたツールを実行するためのパッケージランナー&lt;br /&gt;
&lt;br /&gt;
===Next.jsアプリの作成===&lt;br /&gt;
[[Next.js]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===[[TypeScript]]の導入===&lt;br /&gt;
====ファイル拡張子====&lt;br /&gt;
*https://3chome.net/javascript-typescript/#:~:text=.tsx%EF%BC%88TSX%E3%83%95%E3%82%A1&lt;br /&gt;
*TypeScriptの拡張子&lt;br /&gt;
**.ts :　コードにJSX含まない&lt;br /&gt;
**.tsx :　コードにJSX含む(含まない場合tsxとしてもよいが望ましくない)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====型アサーション====&lt;br /&gt;
&lt;br /&gt;
===導入(旧)===&lt;br /&gt;
----&lt;br /&gt;
*https://facebook.github.io/react/docs/installation.html&lt;br /&gt;
*https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/[[R]]EADME.md#table-of-contents&lt;br /&gt;
*[[React]]のSPAを作成するのによい方法&lt;br /&gt;
 [[npm]] install -g create-react-app&lt;br /&gt;
*https://ja.reactjs.org/docs/create-a-new-react-app.html&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
npx create-react-app my-app&lt;br /&gt;
cd my-app&lt;br /&gt;
npm start&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
*[[React]]はバックエンドロジックやデータベースを持たないが、使いたいものを使えばよい。&lt;br /&gt;
*Babelやwebpackのようなビルドツールも設定なしに利用できる。&lt;br /&gt;
 PS C:\workspaces\vscode\reactlesson&amp;amp;gt; create-react-app react-lesson&lt;br /&gt;
 Creating a new [[React]] app in C:\workspaces\vscode\reactlesson\react-lesson.&lt;br /&gt;
 &lt;br /&gt;
 Installing packages. This might take a couple minutes.&lt;br /&gt;
 Installing react, react-dom, and react-scripts...&lt;br /&gt;
               :&lt;br /&gt;
*アプリケーションが作成されたら実行&lt;br /&gt;
 PS C:\workspaces\vscode\reactlesson&amp;amp;gt; cd react-lesson&lt;br /&gt;
 PS C:\workspaces\vscode\reactlesson&amp;amp;gt; [[npm]] start&lt;br /&gt;
*実行された&lt;br /&gt;
[[File:1086_react01.jpg]]&lt;br /&gt;
*/src/App.js を書き換えてみる&lt;br /&gt;
 import [[React]], { Component } from 'react';&lt;br /&gt;
 import logo from './logo.svg';&lt;br /&gt;
 import './App.css';&lt;br /&gt;
 &lt;br /&gt;
 const element = (&amp;amp;lt;h1&amp;amp;gt;Hello,world&amp;amp;lt;/h1&amp;amp;gt;);&lt;br /&gt;
 class App extends Component {&lt;br /&gt;
   render() {&lt;br /&gt;
     return (&lt;br /&gt;
       element&lt;br /&gt;
     );&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 export default App;&lt;br /&gt;
*反映された&lt;br /&gt;
[[File:1087_react02.jpg]]&lt;br /&gt;
*リリース準備ができたら、以下を実行することで、buildフォルダ以下に最適化されたアプリケーションを作成する&lt;br /&gt;
 [[npm]] run build&lt;br /&gt;
&lt;br /&gt;
==クイックスタート==&lt;br /&gt;
===JSX===&lt;br /&gt;
 const element = &amp;amp;lt;h1&amp;amp;gt;Hello,world!&amp;amp;lt;/h1&amp;amp;gt;;&lt;br /&gt;
*文字列でも、[[HTML]]でもなく、JSX&lt;br /&gt;
*[[JavaScript]]の拡張文法&lt;br /&gt;
*テンプレートと思われるかもしれないが、完全な[[JavaScript]]&lt;br /&gt;
*JSXは[[React]]の要素を生成する&lt;br /&gt;
===JSX表現===&lt;br /&gt;
*どのような[[JavaScript]]の表現も、中括弧で囲むことでJSXに埋め込むことができる&lt;br /&gt;
*const element = (&amp;amp;lt;h1&amp;amp;gt;Hello, {formatName(user)}!&amp;amp;lt;/h1&amp;amp;gt;);&lt;br /&gt;
&lt;br /&gt;
 &amp;amp;lt;!DOCTYPE html&amp;amp;gt;&lt;br /&gt;
 &amp;amp;lt;html&amp;amp;gt;&lt;br /&gt;
   &amp;amp;lt;head&amp;amp;gt;&lt;br /&gt;
     &amp;amp;lt;meta charset=&amp;quot;UTF-8&amp;quot; /&amp;amp;gt;&lt;br /&gt;
     &amp;amp;lt;title&amp;amp;gt;Hello World&amp;amp;lt;/title&amp;amp;gt;&lt;br /&gt;
     &amp;amp;lt;script src=&amp;quot;https://unpkg.com/react@latest/dist/react.js&amp;quot;&amp;amp;gt;&amp;amp;lt;/script&amp;amp;gt;&lt;br /&gt;
     &amp;amp;lt;script src=&amp;quot;https://unpkg.com/react-dom@latest/dist/react-dom.js&amp;quot;&amp;amp;gt;&amp;amp;lt;/script&amp;amp;gt;&lt;br /&gt;
     &amp;amp;lt;script src=&amp;quot;https://unpkg.com/babel-standalone@6.15.0/babel.min.js&amp;quot;&amp;amp;gt;&amp;amp;lt;/script&amp;amp;gt;&lt;br /&gt;
   &amp;amp;lt;/head&amp;amp;gt;&lt;br /&gt;
   &amp;amp;lt;body&amp;amp;gt;&lt;br /&gt;
     &amp;amp;lt;div id=&amp;quot;root&amp;quot;&amp;amp;gt;&amp;amp;lt;/div&amp;amp;gt;&lt;br /&gt;
     &amp;amp;lt;script type=&amp;quot;text/babel&amp;quot;&amp;amp;gt;&lt;br /&gt;
     function formatName(user) {&lt;br /&gt;
         return user.firstName + ' ' + user.lastName;&lt;br /&gt;
     }&lt;br /&gt;
     const user = {firstName:'Hiroto', lastName:'Yagi'};&lt;br /&gt;
     const element = (&amp;amp;lt;h1&amp;amp;gt;Hello, {formatName(user)}!&amp;amp;lt;/h1&amp;amp;gt;); &lt;br /&gt;
     [[React]]DOM.render(&lt;br /&gt;
         element,&lt;br /&gt;
         document.getElementById('root')&lt;br /&gt;
     );&lt;br /&gt;
     &amp;amp;lt;/script&amp;amp;gt;&lt;br /&gt;
   &amp;amp;lt;/body&amp;amp;gt;&lt;br /&gt;
 &amp;amp;lt;/html&amp;amp;gt;&lt;br /&gt;
&lt;br /&gt;
*コンパイルされたJSXは通常の[[JavaScript]]オブジェクト&lt;br /&gt;
*JSXをif文やforループ、変数への割り当て、引数や戻り値に利用できる&lt;br /&gt;
&lt;br /&gt;
 function greeting(user) {&lt;br /&gt;
    var now = new Date();&lt;br /&gt;
    if (5 &amp;amp;lt;= now.getHours() &amp;amp;&amp;amp; now.getHours() &amp;amp;lt;= 12) {&lt;br /&gt;
        return &amp;amp;lt;h1&amp;amp;gt; Good morning {user.firstName + ' ' + user.lastName}.&amp;amp;lt;/h1&amp;amp;gt;;&lt;br /&gt;
    } else {&lt;br /&gt;
        return &amp;amp;lt;h1&amp;amp;gt; Hello {user.firstName + ' ' + user.lastName}.&amp;amp;lt;/h1&amp;amp;gt;;&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
====属性に利用====&lt;br /&gt;
*中括弧を利用して、二重引用符なし(使用すると文字列リテラルとして扱われる)で直接利用できる。&lt;br /&gt;
 &amp;amp;lt;div id=&amp;quot;root&amp;quot;&amp;amp;gt;&amp;amp;lt;/div&amp;amp;gt;&lt;br /&gt;
 &amp;amp;lt;script type=&amp;quot;text/babel&amp;quot;&amp;amp;gt;&lt;br /&gt;
 function greeting(user) {&lt;br /&gt;
     var now = new Date();&lt;br /&gt;
     if (5 &amp;amp;lt;= now.getHours() &amp;amp;&amp;amp; now.getHours() &amp;amp;lt;= 12) {&lt;br /&gt;
         return &amp;amp;lt;h1&amp;amp;gt; Good morning &amp;amp;lt;a href={user.webpageUrl}&amp;amp;gt;{user.firstName + ' ' + user.lastName}&amp;amp;lt;/a&amp;amp;gt;.&amp;amp;lt;/h1&amp;amp;gt;;&lt;br /&gt;
     } else {&lt;br /&gt;
         return &amp;amp;lt;h1&amp;amp;gt; Hello &amp;amp;lt;a href={user.webpageUrl}&amp;amp;gt;{user.firstName + ' ' + user.lastName}&amp;amp;lt;/a&amp;amp;gt;.&amp;amp;lt;/h1&amp;amp;gt;;&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
 const user = {firstName:'Hiroto', lastName:'Yagi', webpageUrl:'http://typea.info'};&lt;br /&gt;
 const element = (&amp;amp;lt;h1&amp;amp;gt;{greeting(user)}&amp;amp;lt;/h1&amp;amp;gt;); &lt;br /&gt;
 [[React]]DOM.render(&lt;br /&gt;
     element,&lt;br /&gt;
     document.getElementById('root')&lt;br /&gt;
 );&lt;br /&gt;
[[File:1089_react04.jpg]]&lt;br /&gt;
====子要素====&lt;br /&gt;
*子要素がない場合、[[XML]]同様　/&amp;amp;gt; で閉じる&lt;br /&gt;
*子要素を含む&lt;br /&gt;
*JSXはHTMLより[[JavaScript]]により近い。ReactDOMはキャメルケースプロパティ(HTMLでは、class がclassName、HTMLではtabindexがtabIndexなど)を持つ&lt;br /&gt;
 function greeting(user) {&lt;br /&gt;
     return &amp;amp;lt;div&amp;amp;gt;&lt;br /&gt;
             &amp;amp;lt;h1&amp;amp;gt; Good morning {user.firstName + ' ' + user.lastName}.&amp;amp;lt;/h1&amp;amp;gt;&lt;br /&gt;
             &amp;amp;lt;h2&amp;amp;gt;&amp;amp;lt;a href={user.webpageUrl}&amp;amp;gt;webpage&amp;amp;lt;/a&amp;amp;gt;&amp;amp;lt;/h2&amp;amp;gt;&lt;br /&gt;
            &amp;amp;lt;/div&amp;amp;gt;&lt;br /&gt;
            ;&lt;br /&gt;
 }&lt;br /&gt;
 const user = {firstName:'Hiroto', lastName:'Yagi', webpageUrl:'http://typea.info'};&lt;br /&gt;
 const element = (greeting(user)); &lt;br /&gt;
 [[React]]DOM.render(&lt;br /&gt;
     element,&lt;br /&gt;
     document.getElementById('root')&lt;br /&gt;
 );&lt;br /&gt;
[[File:1090_react05.jpg]]&lt;br /&gt;
====インジェクション[[攻撃]]の予防====&lt;br /&gt;
*デフォルトで[[React]] DOMは、JSXに埋め込まれた値をレンダリング前にエスケープする&lt;br /&gt;
*明示的にアプリケーションに記述しなくてもインジェクションされないことを保証する&lt;br /&gt;
*XSS[[攻撃]]の予防を助ける&lt;br /&gt;
 function greeting(user, title) {&lt;br /&gt;
     return &amp;amp;lt;div&amp;amp;gt;&lt;br /&gt;
              &amp;amp;lt;h1&amp;amp;gt;{title}&amp;amp;lt;/h1&amp;amp;gt;&lt;br /&gt;
              &amp;amp;lt;h2&amp;amp;gt; Good morning {user.firstName + ' ' + user.lastName}.&amp;amp;lt;/h2&amp;amp;gt;&lt;br /&gt;
              &amp;amp;lt;h2&amp;amp;gt;&amp;amp;lt;a href={user.webpageUrl}&amp;amp;gt;webpage&amp;amp;lt;/a&amp;amp;gt;&amp;amp;lt;/h2&amp;amp;gt;&lt;br /&gt;
            &amp;amp;lt;/div&amp;amp;gt;&lt;br /&gt;
            ;&lt;br /&gt;
 }&lt;br /&gt;
 const title = &amp;quot;&amp;amp;lt;input type='button'&amp;amp;gt;&amp;quot;;&lt;br /&gt;
 const user = {firstName:'Hiroto', lastName:'Yagi', webpageUrl:'http://typea.info'};&lt;br /&gt;
 const element = (greeting(user,title)); &lt;br /&gt;
 [[React]]DOM.render(&lt;br /&gt;
     element,&lt;br /&gt;
     document.getElementById('root')&lt;br /&gt;
 );&lt;br /&gt;
[[File:1091_react06.jpg]]&lt;br /&gt;
====JSX [[R]]epresent オブジェクト====&lt;br /&gt;
*Babelは、[[React]].createElement()を呼び出しコンパイルを行う&lt;br /&gt;
*以下の2つは同じ意味&lt;br /&gt;
 const element1 = (&amp;amp;lt;h1 className='greeting'&amp;amp;gt;hello&amp;amp;lt;/h1&amp;amp;gt;);&lt;br /&gt;
 const element2 = [[React]].createElement('h1',{className:'greeting'},'hello');&lt;br /&gt;
*[[React]].createElement()は、バグを防ぐ手助けをするが、本質的には以下のようなオブジェクトを生成する&lt;br /&gt;
 // 簡易表現&lt;br /&gt;
 const element = {type:'h1',props:{className:'greeting',children:'hello'}};&lt;br /&gt;
*これらの要素を&amp;quot;[[React]] elements&amp;quot;と呼ぶ&lt;br /&gt;
*画面に表示させたいものの記述と考えることができる&lt;br /&gt;
*[[React]]はこれらのオブジェクトを読み、DOMの構築と最新化に利用する    &lt;br /&gt;
===Elementsのレンダリング===&lt;br /&gt;
*Elements は[[React]] アプリケーションの最小のビルディングブロック&lt;br /&gt;
*1つの要素は、画面上に表示するものを表現する&lt;br /&gt;
*ブラウザのDOM要素と異なり、[[React]] Elements はプレーンなオブジェクトで生成のコストは小さい&lt;br /&gt;
*[[React]] DOMは、DOMを[[React]] Elementsに一致するように取り扱う&lt;br /&gt;
====1つの要素を[[DOM]]の中にレンダリング====&lt;br /&gt;
*[[HTML]]どこかに記述する、以下のDIV要素をroot DOM ノードと呼ぶ&lt;br /&gt;
*[[React]] DOM が管理するすべてが、この要素の中にある&lt;br /&gt;
 &amp;amp;lt;div id=&amp;quot;root&amp;quot;&amp;amp;gt;&amp;amp;lt;/div&amp;amp;gt;&lt;br /&gt;
====[[React]]要素の更新====&lt;br /&gt;
*[[React]]要素は不変。一旦生成したら、子要素、属性などは変更できない。&lt;br /&gt;
*UIを更新するには、新しい要素を作成し、[[React]]DOM.rendar()に引き渡す。&lt;br /&gt;
 function tick() {&lt;br /&gt;
   const element = (&amp;amp;lt;div&amp;amp;gt;{(new Date()).toLocaleTimeString()}&amp;amp;lt;/div&amp;amp;gt;);&lt;br /&gt;
   [[React]]DOM.render(&lt;br /&gt;
       element,&lt;br /&gt;
       document.getElementById('root')&lt;br /&gt;
   );&lt;br /&gt;
 }&lt;br /&gt;
 setInterval(tick,1000);&lt;br /&gt;
[[File:1092_react07.jpg]]&lt;br /&gt;
&amp;amp;lt;blockquote&amp;amp;gt;通常の[[React]] アプリケーションでは、[[React]]DOM.rendar()は 一度しか呼びださない。&amp;amp;lt;/blockquote&amp;amp;gt;&lt;br /&gt;
====[[React]]は必要なもののみ更新する====&lt;br /&gt;
*[[React]] DOMは、要素および子要素を前の状態と比較し、DOMの更新が必要な個所にのみ適用する。&lt;br /&gt;
*ブラウザツールで、上記のソースコードを確認する&lt;br /&gt;
[[File:1093_react08.jpg]]&lt;br /&gt;
&amp;amp;lt;blockquote&amp;amp;gt;毎tick()の呼び出しで、すべてのUIツリーを生成するよう記述してるが、変更が発生したテキストノードのみ[[React]] DOMにより更新されている。&amp;amp;lt;/blockquote&amp;amp;gt;&lt;br /&gt;
===コンポーネントと Props===&lt;br /&gt;
*コンポーネントはUIを独立し再利用可能な部分に分割する。&lt;br /&gt;
*概念的にコンポーネントは[[JavaScript]]の関数のようなもの。&lt;br /&gt;
*コンポーネントはpropsと呼ばれる任意の入力を受け付け、[[React]] Elementを返す。&lt;br /&gt;
====コンポーネントの機能とクラス====&lt;br /&gt;
*[[JavaScript]]の関数としてコンポーネントを定義する&lt;br /&gt;
*この関数は有効な[[React]]コンポーネント、なぜなら、単一のprops引数を引数として取り、[[React]] Elementを返す。&lt;br /&gt;
*このようなコンポーネントを&amp;quot;functional&amp;quot;と呼ぶ。&lt;br /&gt;
 function Welcome(props) {&lt;br /&gt;
     return &amp;amp;lt;h1&amp;amp;gt;Hello,{props.name}&amp;amp;lt;/h1&amp;amp;gt;;&lt;br /&gt;
 }&lt;br /&gt;
*ES6のクラスをコンポーネントの定義として利用できる&lt;br /&gt;
 class Welcome extends [[React]].Component {&lt;br /&gt;
     render() {&lt;br /&gt;
         return &amp;amp;lt;h1&amp;amp;gt;Hello,{props.name}&amp;amp;lt;/h1&amp;amp;gt;;&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
*上記2つのコンポーネントは[[React]]の視点からは同じ&lt;br /&gt;
====コンポーネントのレンダリング====&lt;br /&gt;
*Elementは、ユーザー定義コンポーネントも表すことができる&lt;br /&gt;
 function Welcome(props) {&lt;br /&gt;
  return &amp;amp;lt;h1&amp;amp;gt;Hello,{props.name}&amp;amp;lt;/h1&amp;amp;gt;;&lt;br /&gt;
 }&lt;br /&gt;
 const element = &amp;amp;lt;Welcome name='Hiroto' /&amp;amp;gt;&lt;br /&gt;
 [[React]]DOM.render(&lt;br /&gt;
     element,&lt;br /&gt;
     document.getElementById('root')&lt;br /&gt;
 );&lt;br /&gt;
*[[React]]がユーザー定義コンポーネントを表示するときに、JSXの属性からコンポーネントへ&amp;quot;props&amp;quot;としてオブジェクトが渡される。&lt;br /&gt;
&lt;br /&gt;
&amp;amp;lt;blockquote&amp;amp;gt;コンポーネント名はいつも大文字から始める。[[DOM]] タグは、&amp;amp;lt;div /&amp;amp;gt; だが、&amp;amp;lt;Welcome /&amp;amp;gt; はコンポーネントを表現する。Welcomeがスコープに存在すること。&amp;amp;lt;/blockquote&amp;amp;gt;&lt;br /&gt;
====コンポーネントの構成====&lt;br /&gt;
*コンポーネントはその出力において、他のコンポーネントに影響を与えることができる&lt;br /&gt;
*同じコンポーネントをどんなレベルの詳細にも抽象的に利用できる、ボタン、フォーム、ダイアログ、スクリーン&lt;br /&gt;
*[[React]]でこれらは、一般にコンポーネントで表現される&lt;br /&gt;
 function Welcome(props) {&lt;br /&gt;
   return &amp;amp;lt;h1&amp;amp;gt;Hello,{props.name}&amp;amp;lt;/h1&amp;amp;gt;;&lt;br /&gt;
 }&lt;br /&gt;
 function App() {&lt;br /&gt;
   return ( &amp;amp;lt;div&amp;amp;gt;&lt;br /&gt;
       &amp;amp;lt;Welcome name=&amp;quot;Yagi&amp;quot;/&amp;amp;gt;&lt;br /&gt;
       &amp;amp;lt;Welcome name=&amp;quot;Kaela&amp;quot;/&amp;amp;gt;&lt;br /&gt;
       &amp;amp;lt;Welcome name=&amp;quot;Hiroto&amp;quot;/&amp;amp;gt;&lt;br /&gt;
     &amp;amp;lt;/div&amp;amp;gt; );&lt;br /&gt;
 }&lt;br /&gt;
 [[React]]DOM.render(&lt;br /&gt;
     &amp;amp;lt;App /&amp;amp;gt;,&lt;br /&gt;
     document.getElementById('root')&lt;br /&gt;
 );&lt;br /&gt;
*一般的に新しい[[React]]アプリケーションは、一つのAppコンポーネントを最上位に持つ。既存のアプリケーションに[[React]]を統合する場合は、小さなコンポーネント、例えばButtonなど、ボトムアップから開始し、徐々にView階層の最上位にいたる。&lt;br /&gt;
&lt;br /&gt;
&amp;amp;lt;blockquote&amp;amp;gt;コンポーネントは、一つのroot要素を返さなければならない。上記で、Welcome要素を div に含めたのはこのため&amp;amp;lt;/blockquote&amp;amp;gt;&lt;br /&gt;
====Propsは読み取り専用====&lt;br /&gt;
**[[React]]はかなりフレキシブルだが、1つ厳格なルールがある。function だろうと class だろうとコンポーネントはpropsを編集できない。&lt;br /&gt;
===状態とライフサイクル===&lt;br /&gt;
*次のClockコンポーネントを再利用可能にカプセル化する&lt;br /&gt;
 function Clock(props) {&lt;br /&gt;
   return (&lt;br /&gt;
     &amp;amp;lt;div&amp;amp;gt;&lt;br /&gt;
       &amp;amp;lt;h2&amp;amp;gt;{props.date.toLocaleTimeString()}&amp;amp;lt;/h2&amp;amp;gt;&lt;br /&gt;
     &amp;amp;lt;/div&amp;amp;gt;&lt;br /&gt;
   );&lt;br /&gt;
 }&lt;br /&gt;
 function tick() {&lt;br /&gt;
   [[React]]DOM.render(&lt;br /&gt;
       &amp;amp;lt;Clock date={new Date()} /&amp;amp;gt;,&lt;br /&gt;
       document.getElementById('root')&lt;br /&gt;
   );&lt;br /&gt;
 }&lt;br /&gt;
 setInterval(tick, 1000);&lt;br /&gt;
&lt;br /&gt;
[[File:1094_react09.jpg]]&lt;br /&gt;
&lt;br /&gt;
*実装のために、Clockコンポーネントにstateを追加する。&lt;br /&gt;
*状態は、propsと同様だが、private かつ、コンポーネントから完全に制御される&lt;br /&gt;
*クラス宣言したコンポーネントにはいくつかの追加的な機能があるが、local state はこれにあたる&lt;br /&gt;
====関数をクラスに変更する====&lt;br /&gt;
#[[React]].Component を継承して同名のES6クラスを作成する&lt;br /&gt;
#render()メソッドを作成し、処理を移動、functionを削除&lt;br /&gt;
#propsをthis.propsに変更&lt;br /&gt;
 class Clock extends [[React]].Component {&lt;br /&gt;
   render() {&lt;br /&gt;
     return (&lt;br /&gt;
       &amp;amp;lt;div&amp;amp;gt;&lt;br /&gt;
         &amp;amp;lt;h2&amp;amp;gt;{this.props.date.toLocaleTimeString()}&amp;amp;lt;/h2&amp;amp;gt;&lt;br /&gt;
       &amp;amp;lt;/div&amp;amp;gt;&lt;br /&gt;
     );&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
====クラスにローカル状態を追加する====&lt;br /&gt;
*date を props から state へ移動する&lt;br /&gt;
#render()メソッドの中の、this.props.date を this.state.date に変更&lt;br /&gt;
#クラスにコンストラクタを追加し、this.stateの初期状態を記述する&lt;br /&gt;
#&amp;amp;lt;Clock date={new Date()} /&amp;amp;gt; から dateを削除&lt;br /&gt;
 class Clock extends [[React]].Component {&lt;br /&gt;
   constructor(props) {&lt;br /&gt;
     super(props);&lt;br /&gt;
     this.state = {date : new Date()};&lt;br /&gt;
   }&lt;br /&gt;
   render() {&lt;br /&gt;
     return (&lt;br /&gt;
       &amp;amp;lt;div&amp;amp;gt;&lt;br /&gt;
         &amp;amp;lt;h2&amp;amp;gt;{this.state.date.toLocaleTimeString()}&amp;amp;lt;/h2&amp;amp;gt;&lt;br /&gt;
       &amp;amp;lt;/div&amp;amp;gt;&lt;br /&gt;
     );&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
====クラスにライフサイクルメソッドを追加する====&lt;br /&gt;
*多くのコンポーネントを使用するアプリケーションでは、破棄されたコンポーネントのリソースの解放が重要&lt;br /&gt;
*ClockがDOMに最初にレンダリングされるときには、必ずタイマーをセットアップしたい。これを[[React]]では、&amp;quot;mounting&amp;quot; という&lt;br /&gt;
*また、ClockがDOMから取り除かれるときには、タイマーをクリアしたい。これを[[React]]では、&amp;quot;unmounting&amp;quot;という&lt;br /&gt;
*コンポーネントが、mount/unmount されるときに実行される特別なメソッドをクラスに宣言できる&lt;br /&gt;
*componentDidMount()、componentWillUnmount() これらのメソッドはライフサイクルフックと呼ばれる&lt;br /&gt;
*どのようにtimer IDを thisに保存するか&lt;br /&gt;
**this.propsが[[React]]によりセットアップされる間、this.stateは特別な意味を持つ&lt;br /&gt;
**表示に使用しないならば、クラスに自由にフィールドを追加できる&lt;br /&gt;
**render()の中では、それらは利用できないし、ステートも持たない&lt;br /&gt;
*最後に、毎秒実行されるtick()メソッドを実装する。&lt;br /&gt;
*this.setState()でローカルコンポーネントの状態を更新する&lt;br /&gt;
&lt;br /&gt;
 class Clock extends [[React]].Component {&lt;br /&gt;
   constructor(props) {&lt;br /&gt;
     super(props);&lt;br /&gt;
     this.state = {date : new Date()};&lt;br /&gt;
   }&lt;br /&gt;
   componentDidMount() {&lt;br /&gt;
     this.timerID = setInterval(&lt;br /&gt;
       () =&amp;amp;gt; this.tick(),1000&lt;br /&gt;
     );&lt;br /&gt;
   }&lt;br /&gt;
   componentWillUnmount() {&lt;br /&gt;
     clearInterval(this.timerID);&lt;br /&gt;
   }&lt;br /&gt;
   tick() {&lt;br /&gt;
     this.setState({&lt;br /&gt;
       date: new Date()&lt;br /&gt;
     });&lt;br /&gt;
   }&lt;br /&gt;
   render() {&lt;br /&gt;
     return (&lt;br /&gt;
       &amp;amp;lt;div&amp;amp;gt;&lt;br /&gt;
         &amp;amp;lt;h2&amp;amp;gt;{this.state.date.toLocaleTimeString()}&amp;amp;lt;/h2&amp;amp;gt;&lt;br /&gt;
       &amp;amp;lt;/div&amp;amp;gt;&lt;br /&gt;
     );&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
 [[React]]DOM.render(&lt;br /&gt;
   &amp;amp;lt;Clock /&amp;amp;gt;,&lt;br /&gt;
   document.getElementById('root')&lt;br /&gt;
 );&lt;br /&gt;
====状態を正しく使う====&lt;br /&gt;
=====stateを直接操作しない=====&lt;br /&gt;
 // まちがい&lt;br /&gt;
 this.state.comment = 'Hello';&lt;br /&gt;
*上記の代わりに、setState() を利用する&lt;br /&gt;
 // 正しい&lt;br /&gt;
 this.setSatate({comment:'Hello'});&lt;br /&gt;
&amp;amp;lt;blockquote&amp;amp;gt;this.stateを割り当てることができるのは、コンストラクタのみ&amp;amp;lt;/blockquote&amp;amp;gt;&lt;br /&gt;
=====stateは、非同期に更新される=====&lt;br /&gt;
*[[React]]は、複数のsetState() をパフォーマンスのためにまとめて一度に処理する。&lt;br /&gt;
*このため、this.propsとthis.stateは非同期に更新される&lt;br /&gt;
*これらの値を信頼して、次の状態への計算を行うべきではない&lt;br /&gt;
 // まちがい&lt;br /&gt;
 this.setState({&lt;br /&gt;
   counter: this.state.counter + this.props.increament,&lt;br /&gt;
 });&lt;br /&gt;
*修正するには、オブジェクトではなく関数を受け取る、setState()を使用する&lt;br /&gt;
*関数は、ひとつ前の状態(state)を最初の引数として、更新時のpropsを2つ目の引数として取る&lt;br /&gt;
 // 正しい&lt;br /&gt;
 this.setState((prevState, props) =&amp;amp;gt; ({&lt;br /&gt;
   counter: prevState.counter + prpos.increament&lt;br /&gt;
 }));&lt;br /&gt;
*通常の関数でもよい&lt;br /&gt;
 // 正しい&lt;br /&gt;
 this.setState(function(prevState, props) {&lt;br /&gt;
   return { counter: prevState.counter + props.increament };&lt;br /&gt;
 });&lt;br /&gt;
=====状態の更新はマージされる=====&lt;br /&gt;
*setState()を呼び出すと、[[React]]は、現在のstateに提供したオブジェクトをマージする&lt;br /&gt;
*例えば、いくつかの独立した変数を含む場合&lt;br /&gt;
 constructor(props) {&lt;br /&gt;
   super(props);&lt;br /&gt;
   this.state = {&lt;br /&gt;
     posts: []&lt;br /&gt;
     comments: []&lt;br /&gt;
   };&lt;br /&gt;
 }&lt;br /&gt;
*これらを別のsetState() で更新&lt;br /&gt;
 componentDidMount() {&lt;br /&gt;
   fetchPosts().then(response =&amp;amp;gt; { this.setState({ posts: response.posts }); });&lt;br /&gt;
   fetchComments().then(response =&amp;amp;gt; { this.setState({ commentss: response.comments }); });&lt;br /&gt;
 }&lt;br /&gt;
*マージはシャローなので、setState({comment}) は、this.state.posts を損なわずに、this.state.comments を置き換える&lt;br /&gt;
====データは下へ流れる====&lt;br /&gt;
*親だけでなく子コンポーネントも確実にステートフルかステートレスか知ることはできない。&lt;br /&gt;
*状態はしばしばローカルから呼び出されるかカプセル化されていて、他からアクセスできない。&lt;br /&gt;
*コンポーネントは、自身の状態をpropsを通して子コンポーネントに渡す&lt;br /&gt;
 &amp;amp;lt;h2&amp;amp;gt;It is {this.state.date.toLocalTimeString()}.&amp;amp;lt;/h2&amp;amp;gt;&lt;br /&gt;
*これは、ユーザー定義コンポーネントでも動作する&lt;br /&gt;
&amp;amp;lt;FormattedDate date={this.state.date} /&amp;amp;gt;&lt;br /&gt;
*FormattedDateコンポーネントは、propsにdateを受け取り、Clockの状態が何かは知らない。&lt;br /&gt;
 function FormatterDate(props) {&lt;br /&gt;
   return &amp;amp;lt;h2&amp;amp;gt;It is {props.date.toLocaleTimeString()}.&amp;amp;lt;/h2&amp;amp;gt;;&lt;br /&gt;
 }&lt;br /&gt;
*これは一般的に、トップダウン、もしくは、ユニディレクショナル データフローという&lt;br /&gt;
*状態は常に特定のコンポーネントに属する。&lt;br /&gt;
*データやUIは状態に由来し、ツリーのより下のコンポーネントにのみ影響を与えることができる&lt;br /&gt;
===イベントの処理===&lt;br /&gt;
*[[React]] 要素のイベント処理は、DOMでの処理ととても似ているが、いくつかシンタックスの差異がある。&lt;br /&gt;
**[[React]]イベントは、ロウアーケースではなく、キャメルケース&lt;br /&gt;
**JSXでは、stringではなく、関数をイベントハンドラーとして渡す。&lt;br /&gt;
&lt;br /&gt;
=====[[HTML]]=====&lt;br /&gt;
 &amp;amp;lt;button onclick=&amp;quot;test()&amp;quot; /&amp;amp;gt;&lt;br /&gt;
=====[[React]]=====&lt;br /&gt;
 &amp;amp;lt;button onClick={test} /&amp;amp;gt;&lt;br /&gt;
&lt;br /&gt;
*もう一つの違いは、[[React]]では、falseを返しデフォルトのふるまいを防止することができない。&lt;br /&gt;
*明示的に、preventDefault を呼び出す必要がある。&lt;br /&gt;
&lt;br /&gt;
=====[[HTML]]でデフォルトの新しいページを開くリンクのふるまいを防止する=====&lt;br /&gt;
 &amp;amp;lt;a href=&amp;quot;#&amp;quot; onclick=&amp;quot;console.log('hoge'); return false&amp;quot; &amp;amp;gt;Click&amp;amp;lt;/a&amp;amp;gt;&lt;br /&gt;
=====[[React]]=====&lt;br /&gt;
 function ActionLink() {&lt;br /&gt;
   function handleClick(e) {&lt;br /&gt;
     e.preventDefault();&lt;br /&gt;
     console.log('hoge');&lt;br /&gt;
   }&lt;br /&gt;
   return (&lt;br /&gt;
     &amp;amp;lt;a href=&amp;quot;#&amp;quot; onClick={handleClick} &amp;amp;gt;Click&amp;amp;lt;/a&amp;amp;gt;&lt;br /&gt;
   )&lt;br /&gt;
 } &lt;br /&gt;
*e は、本物ではないイベント。Reactでは、[https://www.w3.org/TR/DOM-Level-3-Events/ W3C]に合わせるために定義している。&lt;br /&gt;
*なので、ブラウザの互換性を心配する必要はない。[https://facebook.github.io/react/docs/events.html リファレンス]を参照&lt;br /&gt;
*[[React]]では、addEventListenerを通常呼び出す必要はない。要素が最初にレンダリングされるときに提供される&lt;br /&gt;
*ES6のクラスを使用するときの一般的なパターン、例えば、Toggle ボタン&lt;br /&gt;
 class Toggle extends [[React]].Component {&lt;br /&gt;
   constructor(props) {&lt;br /&gt;
     super(props);&lt;br /&gt;
     this.state = {isToggleOn: true};&lt;br /&gt;
     this.handleClick = this.handleClick.bind(this);&lt;br /&gt;
   }&lt;br /&gt;
   handleClick() {&lt;br /&gt;
     this.setState(prevStae =&amp;amp;gt; ({&lt;br /&gt;
       isToggleOn: !prevStae.isToggleOn&lt;br /&gt;
     }));&lt;br /&gt;
   }&lt;br /&gt;
   render() {&lt;br /&gt;
     return (&lt;br /&gt;
       &amp;amp;lt;button onClick={this.handleClick} &amp;amp;gt;&lt;br /&gt;
         {this.state.isToggleOn?&amp;quot;ON&amp;quot;:&amp;quot;OFF&amp;quot;}&lt;br /&gt;
       &amp;amp;lt;/button&amp;amp;gt;&lt;br /&gt;
     );&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
 [[React]]DOM.render(&lt;br /&gt;
   &amp;amp;lt;Toggle /&amp;amp;gt;,&lt;br /&gt;
   document.getElementById('root')&lt;br /&gt;
 );&lt;br /&gt;
*この文法の問題点は、LoggingButtonがレンダリングされるたびに、異なったコールバックが生成されること&lt;br /&gt;
*多くのケースで、これは問題ないが、このコールバックが下位のコンポーネントにpropとして渡される場合、コンポーネントは余分にレンダリングすることになる。&lt;br /&gt;
*コンストラクタでバインドするか、プロパティイニシャライザでバインドすることを推奨する。&lt;br /&gt;
===条件付きのレンダリング===&lt;br /&gt;
*[[React]]では、必要なら、振る舞いがカプセルかされた他と異なったコンポーネントを作成できる。&lt;br /&gt;
*Reactの条件付きレンダリングは、[[JavaScript]]の条件が動作するのと同じ方法で動作する。&lt;br /&gt;
*[[JavaScript]]のifのような演算子もしくは、条件演算子は、現在の状態を表した要素を作成するための、ReactがUIをそれに一致させることを許す。&lt;br /&gt;
=====以下の2つのコンポーネントについて考える=====&lt;br /&gt;
*ユーザーがログインしているか否かによって使い分けたい。&lt;br /&gt;
*isLoggedIn により、異なるレンダリングがなされる。&lt;br /&gt;
 function UserGreeting(props){&lt;br /&gt;
    return &amp;amp;lt;h1&amp;amp;gt;Welcome to back!&amp;amp;lt;/h1&amp;amp;gt;&lt;br /&gt;
 }    &lt;br /&gt;
 function GuestGreeting(props) {&lt;br /&gt;
    return &amp;amp;lt;h1&amp;amp;gt;Please Sign up!&amp;amp;lt;/h1&amp;amp;gt;&lt;br /&gt;
 }&lt;br /&gt;
 function Greeting(props) {&lt;br /&gt;
    const isLoggedIn = props.isLoggedIn;&lt;br /&gt;
    if (isLoggedIn) {&lt;br /&gt;
      return &amp;amp;lt;UserGreeting /&amp;amp;gt;&lt;br /&gt;
    } else {&lt;br /&gt;
      return &amp;amp;lt;GuestGreeting /&amp;amp;gt;&lt;br /&gt;
    }&lt;br /&gt;
 }    &lt;br /&gt;
 [[React]]DOM.render(&lt;br /&gt;
   &amp;amp;lt;Greeting isLoggedIn={true} /&amp;amp;gt;,&lt;br /&gt;
   document.getElementById('root')&lt;br /&gt;
 );&lt;br /&gt;
====要素変数====&lt;br /&gt;
*要素を保持するのに変数を利用できる。&lt;br /&gt;
*これは、出力結果が変わらない間に、条件によりコンポーネントの一部をレンダリングするのを助ける。&lt;br /&gt;
 function LoginButton(props) {&lt;br /&gt;
    return (&lt;br /&gt;
      &amp;amp;lt;button onClick={props.onClick} &amp;amp;gt;&lt;br /&gt;
        Login      &lt;br /&gt;
      &amp;amp;lt;/button&amp;amp;gt;&lt;br /&gt;
    );&lt;br /&gt;
 }&lt;br /&gt;
 function LogoutButton(props) {&lt;br /&gt;
    return (&lt;br /&gt;
      &amp;amp;lt;button onClick={props.onClick} &amp;amp;gt;&lt;br /&gt;
        Logout      &lt;br /&gt;
      &amp;amp;lt;/button&amp;amp;gt;&lt;br /&gt;
    );&lt;br /&gt;
 }&lt;br /&gt;
 class LoginControl extends [[React]].Component {&lt;br /&gt;
    constructor(props) {&lt;br /&gt;
      super(props);&lt;br /&gt;
      this.handleLoginClick = this.handleLoginClick.bind(this);&lt;br /&gt;
      this.handleLogoutClick = this.handleLogoutClick.bind(this);&lt;br /&gt;
      this.state = {isLoggedIn: false};&lt;br /&gt;
    }&lt;br /&gt;
    handleLoginClick() {&lt;br /&gt;
      this.setState({isLoggedIn: true});&lt;br /&gt;
    }&lt;br /&gt;
    handleLogoutClick(){&lt;br /&gt;
      this.setState({isLoggedIn: false});&lt;br /&gt;
    }&lt;br /&gt;
    render() {&lt;br /&gt;
      const isLoggedIn = this.state.isLoggedIn;&lt;br /&gt;
      let button = null;&lt;br /&gt;
      if (isLoggedIn) {&lt;br /&gt;
        button = &amp;amp;lt;LogoutButton onClick={this.handleLogoutClick} /&amp;amp;gt;&lt;br /&gt;
      } else {&lt;br /&gt;
        button = &amp;amp;lt;LoginButton onClick={this.handleLoginClick} /&amp;amp;gt;&lt;br /&gt;
      }&lt;br /&gt;
      return (&amp;amp;lt;div&amp;amp;gt;{button}&amp;amp;lt;/div&amp;amp;gt;);&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 [[React]]DOM.render(&lt;br /&gt;
   &amp;amp;lt;LoginControl /&amp;amp;gt;,&lt;br /&gt;
   document.getElementById('root')&lt;br /&gt;
 );&lt;br /&gt;
[[File:1085_react_debug.jpg]]&lt;br /&gt;
====インラインif と 論理 &amp;amp;&amp;amp; 演算子====&lt;br /&gt;
*true &amp;amp;&amp;amp; 演算子の場合評価され、false &amp;amp;&amp;amp; の場合、falseとなり[[React]]は無視する&lt;br /&gt;
 function MailBox(props) {&lt;br /&gt;
    const unreadMessages = props.unreadMessages;&lt;br /&gt;
    return  (&lt;br /&gt;
      &amp;amp;lt;div&amp;amp;gt;&lt;br /&gt;
        &amp;amp;lt;h1&amp;amp;gt;Hello!&amp;amp;lt;/h1&amp;amp;gt;&lt;br /&gt;
        {unreadMessages.length &amp;amp;gt; 0 &amp;amp;&amp;amp;&lt;br /&gt;
          &amp;amp;lt;h2&amp;amp;gt;&lt;br /&gt;
            You have {unreadMessages.length} unread messages.&lt;br /&gt;
          &amp;amp;lt;/h2&amp;amp;gt;&lt;br /&gt;
        }&lt;br /&gt;
      &amp;amp;lt;/div&amp;amp;gt;&lt;br /&gt;
    );&lt;br /&gt;
 }&lt;br /&gt;
 const messages = ['message1','message2'];&lt;br /&gt;
 [[React]]DOM.render(&lt;br /&gt;
   &amp;amp;lt;MailBox unreadMessages={messages} /&amp;amp;gt;,&lt;br /&gt;
   document.getElementById('root')&lt;br /&gt;
 );&lt;br /&gt;
====インライン if-else とコンディション演算子====&lt;br /&gt;
*条件 ? true : false&lt;br /&gt;
 function UserGreeting(props){&lt;br /&gt;
     return &amp;amp;lt;h1&amp;amp;gt;Welcome to back!&amp;amp;lt;/h1&amp;amp;gt;&lt;br /&gt;
 }    &lt;br /&gt;
 function GuestGreeting(props) {&lt;br /&gt;
     return &amp;amp;lt;h1&amp;amp;gt;Please Sign up!&amp;amp;lt;/h1&amp;amp;gt;&lt;br /&gt;
 }&lt;br /&gt;
 function Greeting(props) {&lt;br /&gt;
     const isLoggedIn = props.isLoggedIn;&lt;br /&gt;
     return (&lt;br /&gt;
       &amp;amp;lt;div&amp;amp;gt;&lt;br /&gt;
       {isLoggedIn ? (&lt;br /&gt;
           &amp;amp;lt;UserGreeting /&amp;amp;gt;&lt;br /&gt;
         ) : (&lt;br /&gt;
           &amp;amp;lt;GuestGreeting /&amp;amp;gt;&lt;br /&gt;
         )&lt;br /&gt;
       }&lt;br /&gt;
       &amp;amp;lt;/div&amp;amp;gt;&lt;br /&gt;
     );&lt;br /&gt;
 }    &lt;br /&gt;
 [[React]]DOM.render(&lt;br /&gt;
   &amp;amp;lt;Greeting isLoggedIn={false} /&amp;amp;gt;,&lt;br /&gt;
   document.getElementById('root')&lt;br /&gt;
 );&lt;br /&gt;
====コンポーネントのレンダリングさせない====&lt;br /&gt;
*他のコンポーネントからレンダリングされたとしてもコンポーネントを隠したい場合、render出力の代わりにnullを返す&lt;br /&gt;
 function WarningBanner(props){&lt;br /&gt;
   if(!props.warn) {&lt;br /&gt;
     return null;&lt;br /&gt;
   }&lt;br /&gt;
   return (&lt;br /&gt;
     &amp;amp;lt;div&amp;amp;gt;Warning!&amp;amp;lt;/div&amp;amp;gt;&lt;br /&gt;
   );&lt;br /&gt;
 }&lt;br /&gt;
 class Page extends [[React]].Component {&lt;br /&gt;
   constructor(props) {&lt;br /&gt;
     super(props);&lt;br /&gt;
     this.state = {showWarning : true}&lt;br /&gt;
     this.handleToggleClick = this.handleToggleClick.bind(this);&lt;br /&gt;
   }&lt;br /&gt;
   handleToggleClick() {&lt;br /&gt;
     this.setState(prevState =&amp;amp;gt;({showWarning : !prevState.showWarning}));&lt;br /&gt;
   }&lt;br /&gt;
   render() {&lt;br /&gt;
     return (&lt;br /&gt;
       &amp;amp;lt;div&amp;amp;gt;&lt;br /&gt;
         &amp;amp;lt;WarningBanner warn={this.state.showWarning} /&amp;amp;gt;&lt;br /&gt;
         &amp;amp;lt;button onClick={this.handleToggleClick}&amp;amp;gt;&lt;br /&gt;
           {this.state.showWarning ? 'Hide' : 'Show'}&lt;br /&gt;
         &amp;amp;lt;/button&amp;amp;gt;&lt;br /&gt;
       &amp;amp;lt;/div&amp;amp;gt;&lt;br /&gt;
     );&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 [[React]]DOM.render(&lt;br /&gt;
   &amp;amp;lt;Page /&amp;amp;gt;,&lt;br /&gt;
   document.getElementById('root')&lt;br /&gt;
 );&lt;br /&gt;
[[File:1095_react10.jpg]]&lt;br /&gt;
===リストとキー===&lt;br /&gt;
=====[[JavaScript]]でリストの変換には、map()を利用する=====&lt;br /&gt;
 const numbers = [1,2,3,4,5];&lt;br /&gt;
 const doubled = numbers.map((number)=&amp;amp;gt; number * 2);&lt;br /&gt;
 console.log(doubled)&lt;br /&gt;
 &amp;amp;gt; [2, 4, 6, 8, 10]&lt;br /&gt;
*[[React]] では同様に配列をリストに変換する&lt;br /&gt;
====複数のコンポーネントをレンダリングする====&lt;br /&gt;
 const fruits = ['apple','orange','grape','banana'];&lt;br /&gt;
 const listItems = fruits.map((fruit) =&amp;amp;gt; &amp;amp;lt;li&amp;amp;gt;{fruit}&amp;amp;lt;/li&amp;amp;gt;);&lt;br /&gt;
 [[React]]DOM.render(&lt;br /&gt;
   &amp;amp;lt;ol&amp;amp;gt;{listItems}&amp;amp;lt;/ol&amp;amp;gt;,&lt;br /&gt;
   document.getElementById('root')&lt;br /&gt;
 );&lt;br /&gt;
&lt;br /&gt;
[[File:1096_react11.jpg]]&lt;br /&gt;
====基本的なリストコンポーネント====&lt;br /&gt;
*通常リストはコンポーネントに含まれる&lt;br /&gt;
=====Keys=====&lt;br /&gt;
*keyを指定しないと警告がでる&lt;br /&gt;
*keyは、[[React]]が、どのアイテムが登録、変更、削除されたのか特定するのに役立つ&lt;br /&gt;
*文字列で兄弟間でユニークな値を設定するのが望ましい&lt;br /&gt;
 function FruitList(props) {&lt;br /&gt;
   const fruits = props.fruits;&lt;br /&gt;
   const listItems = fruits.map((fruit) =&amp;amp;gt; &amp;amp;lt;li key={fruit}&amp;amp;gt;{fruit}&amp;amp;lt;/li&amp;amp;gt;);&lt;br /&gt;
   return (&lt;br /&gt;
     &amp;amp;lt;ol&amp;amp;gt;{listItems}&amp;amp;lt;/ol&amp;amp;gt; &lt;br /&gt;
   );&lt;br /&gt;
 } &lt;br /&gt;
 const fruits = ['apple','orange','grape','banana'];&lt;br /&gt;
 [[React]]DOM.render(&lt;br /&gt;
   &amp;amp;lt;FruitList fruits={fruits}/&amp;amp;gt;,&lt;br /&gt;
   document.getElementById('root')&lt;br /&gt;
 );&lt;br /&gt;
====コンポーネントをKeyと取り出す====&lt;br /&gt;
*Keyが意味を持つのは、配列を囲むコンテキストにおいて&lt;br /&gt;
*兄弟間で同じKeyを持つとエラーとなる&lt;br /&gt;
 function ListItem(props) {&lt;br /&gt;
   // この&amp;amp;lt;li&amp;amp;gt; にKeyを設定するのは、ここがルートになるため間違い&lt;br /&gt;
   return &amp;amp;lt;li&amp;amp;gt;{props.value}&amp;amp;lt;/li&amp;amp;gt;&lt;br /&gt;
 }&lt;br /&gt;
 function FruitList(props) {&lt;br /&gt;
   const fruits = props.fruits;&lt;br /&gt;
   // &amp;amp;lt;ListItem&amp;amp;gt;の配列となるため、ここでKeyを指定するのが正しい&lt;br /&gt;
   const listItems = fruits.map((fruit) =&amp;amp;gt; &amp;amp;lt;ListItem key={fruit} value={fruit} /&amp;amp;gt;);&lt;br /&gt;
   return (&lt;br /&gt;
     &amp;amp;lt;ol&amp;amp;gt;{listItems}&amp;amp;lt;/ol&amp;amp;gt; &lt;br /&gt;
   );&lt;br /&gt;
 } &lt;br /&gt;
 const fruits = ['apple','orange','grape','banana'];&lt;br /&gt;
 [[React]]DOM.render(&lt;br /&gt;
   &amp;amp;lt;FruitList fruits={fruits}/&amp;amp;gt;,&lt;br /&gt;
   document.getElementById('root')&lt;br /&gt;
 );&lt;br /&gt;
====JSXでmap()を埋め込む====&lt;br /&gt;
*中括弧のインラインにmap()を置くことができる&lt;br /&gt;
 function ListItem(props) {&lt;br /&gt;
   return &amp;amp;lt;li&amp;amp;gt;{props.value}&amp;amp;lt;/li&amp;amp;gt;&lt;br /&gt;
 }&lt;br /&gt;
 function FruitList(props) {&lt;br /&gt;
   const fruits = props.fruits;&lt;br /&gt;
   return (&lt;br /&gt;
     &amp;amp;lt;ol&amp;amp;gt;{fruits.map((fruit) =&amp;amp;gt; &amp;amp;lt;ListItem key={fruit} value={fruit} /&amp;amp;gt;)}&amp;amp;lt;/ol&amp;amp;gt; &lt;br /&gt;
   );&lt;br /&gt;
&lt;br /&gt;
 } &lt;br /&gt;
 const fruits = ['apple','orange','grape','banana'];&lt;br /&gt;
 [[React]]DOM.render(&lt;br /&gt;
   &amp;amp;lt;FruitList fruits={fruits}/&amp;amp;gt;,&lt;br /&gt;
   document.getElementById('root')&lt;br /&gt;
 );&lt;br /&gt;
===Form===&lt;br /&gt;
*HTML Formは、[[React]]では、少し他のDOMとは動作が異なる。&lt;br /&gt;
*なぜなら Fromは通常内部状態をもつから。&lt;br /&gt;
====コントロールされたコンポーネント====&lt;br /&gt;
*[[HTML]]でFormは、自身の状態を維持しユーザー入力に基づいて状態を更新する。&lt;br /&gt;
*[[React]]では、変化可能な状態はコンポーネントのstateプロパティに保持し、setState()からのみ更新される。&lt;br /&gt;
*&amp;quot;single source of truth&amp;quot;として[[React]] stateを作成することにより2つを結びつけることができる。&lt;br /&gt;
*[[React]]コンポーネントはFormまたコントロールでユーザー入力により、何が起きたかを描画する。&lt;br /&gt;
*input Form 要素の値は、[[React]]によりこの方法で制御される。&lt;br /&gt;
*これは、「コントロールされたコンポーネント」と呼ばれる。&lt;br /&gt;
&lt;br /&gt;
 class NameForm extends [[React]].Component {&lt;br /&gt;
   constructor(props) {&lt;br /&gt;
     super(props);&lt;br /&gt;
     this.state = {value : ''};&lt;br /&gt;
     this.handleChange = this.handleChange.bind(this);&lt;br /&gt;
     this.handleSubmit = this.handleSubmit.bind(this);&lt;br /&gt;
   }&lt;br /&gt;
   handleChange(event) {&lt;br /&gt;
     this.setState({value : event.target.value });&lt;br /&gt;
   }&lt;br /&gt;
   handleSubmit(event) {&lt;br /&gt;
     alert('A name was submitted ' + this.state.value);&lt;br /&gt;
     event.preventDefault();&lt;br /&gt;
   }&lt;br /&gt;
   render() {&lt;br /&gt;
     return(&lt;br /&gt;
       &amp;amp;lt;form onSubmit={this.handleSubmit}&amp;amp;gt;&lt;br /&gt;
          &amp;amp;lt;label&amp;amp;gt;Name: &amp;amp;lt;input type=&amp;quot;text&amp;quot; value={this.state.value} onChange={this.handleChange} /&amp;amp;gt;&amp;amp;lt;/label&amp;amp;gt;&lt;br /&gt;
          &amp;amp;lt;input type=&amp;quot;submit&amp;quot; value=&amp;quot;Submit&amp;quot;/&amp;amp;gt;&lt;br /&gt;
       &amp;amp;lt;/form&amp;amp;gt;&lt;br /&gt;
     );&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
 [[React]]DOM.render(&lt;br /&gt;
   &amp;amp;lt;NameForm /&amp;amp;gt;,&lt;br /&gt;
   document.getElementById('root')&lt;br /&gt;
 );&lt;br /&gt;
[[File:1097_react12.jpg]]&lt;br /&gt;
*valueが、Form要素に設定されると、表示されるvalueは、常にthis.state.valueとなる&lt;br /&gt;
*すべてのキーストロークで、handleChangeが起動し、[[React]]のstateを更新する&lt;br /&gt;
*表示されるvalueも更新される&lt;br /&gt;
 handleChange(event) {&lt;br /&gt;
   this.setState({value : event.target.value.toUpperCase() });&lt;br /&gt;
 }&lt;br /&gt;
====textarea/select タグ====&lt;br /&gt;
 class SelectParts extends [[React]].Component {&lt;br /&gt;
   constructor(props){&lt;br /&gt;
     super(props);&lt;br /&gt;
     this.state = {value: 'coconuts'};&lt;br /&gt;
     this.handleChange = this.handleChange.bind(this);&lt;br /&gt;
   }&lt;br /&gt;
   handleChange(event) {&lt;br /&gt;
     this.setState({value: event.target.value});&lt;br /&gt;
   }&lt;br /&gt;
   render(){&lt;br /&gt;
     return(&lt;br /&gt;
       &amp;amp;lt;label&amp;amp;gt;Select:&lt;br /&gt;
         &amp;amp;lt;select value={this.state.value} onChange={this.handleChange}&amp;amp;gt;&lt;br /&gt;
           &amp;amp;lt;option value=&amp;quot;grapefruit&amp;quot;&amp;amp;gt;Grape Fruit&amp;amp;lt;/option&amp;amp;gt;&lt;br /&gt;
           &amp;amp;lt;option value=&amp;quot;lime&amp;quot;&amp;amp;gt;Lime&amp;amp;lt;/option&amp;amp;gt;&lt;br /&gt;
           &amp;amp;lt;option value=&amp;quot;coconuts&amp;quot;&amp;amp;gt;Coconuts&amp;amp;lt;/option&amp;amp;gt;&lt;br /&gt;
           &amp;amp;lt;option value=&amp;quot;mango&amp;quot;&amp;amp;gt;Mango&amp;amp;lt;/option&amp;amp;gt;&lt;br /&gt;
         &amp;amp;lt;/select&amp;amp;gt;&lt;br /&gt;
       &amp;amp;lt;/label&amp;amp;gt;&lt;br /&gt;
     );&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
 class TextareaParts extends [[React]].Component {&lt;br /&gt;
   constructor(props){&lt;br /&gt;
     super(props);&lt;br /&gt;
     this.state = {&lt;br /&gt;
       value : 'なにか書いて'&lt;br /&gt;
     };&lt;br /&gt;
     this.handleChange = this.handleChange.bind(this);&lt;br /&gt;
   }&lt;br /&gt;
   handleChange(event) {&lt;br /&gt;
     this.setState({value : event.target.value});&lt;br /&gt;
   }&lt;br /&gt;
   render(){&lt;br /&gt;
     return (&lt;br /&gt;
         &amp;amp;lt;label&amp;amp;gt;Textarea:&amp;amp;lt;textarea value={this.state.value} onChange={this.handleChange} /&amp;amp;gt;&amp;amp;lt;/label&amp;amp;gt;&lt;br /&gt;
     );&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
 [[React]]DOM.render(&lt;br /&gt;
   &amp;amp;lt;div&amp;amp;gt;&lt;br /&gt;
     &amp;amp;lt;SelectParts /&amp;amp;gt;&lt;br /&gt;
     &amp;amp;lt;TextareaParts /&amp;amp;gt;&lt;br /&gt;
   &amp;amp;lt;/div&amp;amp;gt;,&lt;br /&gt;
   document.getElementById('root')&lt;br /&gt;
 );&lt;br /&gt;
====複数入力項目の処理====&lt;br /&gt;
*複数のコントロールされた入力要素を処理したい場合、name属性を各要素に追加する&lt;br /&gt;
*ハンドラー関数で、event.target.name の値に基づいて、どの要素か判定&lt;br /&gt;
*ES6 [https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Operators/Object_initializer#Computed_property_names 計算されたプロパティ名]構文をkey状態を更新するのに使用&lt;br /&gt;
 class Reservation extends [[React]].Component {&lt;br /&gt;
   constructor(props) {&lt;br /&gt;
     super(props);&lt;br /&gt;
     this.state = {&lt;br /&gt;
       isGoing: true,&lt;br /&gt;
       numberOfGuests: 2&lt;br /&gt;
     };&lt;br /&gt;
     this.handleInputChange = this.handleInputChange.bind(this);&lt;br /&gt;
   }&lt;br /&gt;
   handleInputChange(event) {&lt;br /&gt;
     const target = event.target;&lt;br /&gt;
     const value = (target.type == 'checkbox') ? target.checked : target.value;&lt;br /&gt;
     const name = target.name;&lt;br /&gt;
     this.setState({[name]: value});&lt;br /&gt;
   }&lt;br /&gt;
   render(){&lt;br /&gt;
     return (&lt;br /&gt;
       &amp;amp;lt;form&amp;amp;gt;&lt;br /&gt;
         &amp;amp;lt;label&amp;amp;gt;Is going:&amp;amp;lt;input name=&amp;quot;isGoing&amp;quot; type=&amp;quot;checkbox&amp;quot; checked={this.state.isGoing} onChange={this.handleInputChange}/&amp;amp;gt;&amp;amp;lt;/label&amp;amp;gt;&lt;br /&gt;
         &amp;amp;lt;br /&amp;amp;gt;&lt;br /&gt;
         &amp;amp;lt;label&amp;amp;gt;Number of guests:&amp;amp;lt;input name=&amp;quot;numberOfGuests&amp;quot; type=&amp;quot;number&amp;quot; value={this.state.numberOfGuests} onChange={this.handleInputChange}/&amp;amp;gt;&amp;amp;lt;/label&amp;amp;gt;&lt;br /&gt;
       &amp;amp;lt;/form&amp;amp;gt;&lt;br /&gt;
     );&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
 [[React]]DOM.render(&lt;br /&gt;
   &amp;amp;lt;div&amp;amp;gt;&lt;br /&gt;
     &amp;amp;lt;[[R]]eservation /&amp;amp;gt;&lt;br /&gt;
   &amp;amp;lt;/div&amp;amp;gt;,&lt;br /&gt;
   document.getElementById('root')&lt;br /&gt;
 );&lt;br /&gt;
[[File:1098_react13.jpg]]&lt;br /&gt;
====コントロールされたコンポーネント以外の方法====&lt;br /&gt;
*コントロールされたコンポーネントを利用するのが、冗長な場合がある。&lt;br /&gt;
*入力フォームを実装するための、[https://facebook.github.io/react/docs/uncontrolled-components.html コントロールされないコンポーネント]を参照。&lt;br /&gt;
===状態を持ち上げる===&lt;br /&gt;
*いくつかのコンポーネントは同じ変更をデータに反映させることを必要とする。&lt;br /&gt;
*共有状態をそれらの、最も近い共通の祖先に持ち上げることを推奨する。&lt;br /&gt;
=====水が沸騰しているかどうかの計算を行う。=====&lt;br /&gt;
 function BoilingVerdict(props) {&lt;br /&gt;
   if (props.celsius &amp;amp;gt;= 100) {&lt;br /&gt;
     return &amp;amp;lt;p&amp;amp;gt;The water would boil.&amp;amp;lt;/p&amp;amp;gt;;&lt;br /&gt;
   }&lt;br /&gt;
   return &amp;amp;lt;p&amp;amp;gt;The water would not boil.&amp;amp;lt;/p&amp;amp;gt;&lt;br /&gt;
 }&lt;br /&gt;
 class Calculator extends [[React]].Component {&lt;br /&gt;
   constructor(props) {&lt;br /&gt;
     super(props);&lt;br /&gt;
     this.handleChange = this.handleChange.bind(this);&lt;br /&gt;
     this.state = {temprature: ''};&lt;br /&gt;
   }&lt;br /&gt;
   handleChange(e){&lt;br /&gt;
     this.setState({temprature: e.target.value});&lt;br /&gt;
   }&lt;br /&gt;
   render(){&lt;br /&gt;
     const temprature = this.state.temprature;&lt;br /&gt;
     return (&lt;br /&gt;
       &amp;amp;lt;fieldset&amp;amp;gt;&lt;br /&gt;
         &amp;amp;lt;legend&amp;amp;gt;Enter temprature in Celsius:&amp;amp;lt;/legend&amp;amp;gt;&lt;br /&gt;
         &amp;amp;lt;input value={temprature} onChange={this.handleChange} /&amp;amp;gt;&lt;br /&gt;
         &amp;amp;lt;BoilingVerdict celsius={parseFloat(temprature)} /&amp;amp;gt;  &lt;br /&gt;
       &amp;amp;lt;/fieldset&amp;amp;gt;&lt;br /&gt;
     );&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
 [[React]]DOM.render(&lt;br /&gt;
   &amp;amp;lt;div&amp;amp;gt;&lt;br /&gt;
     &amp;amp;lt;Calculator /&amp;amp;gt;&lt;br /&gt;
   &amp;amp;lt;/div&amp;amp;gt;,&lt;br /&gt;
   document.getElementById('root')&lt;br /&gt;
 );&lt;br /&gt;
[[File:1099_react14.jpg]]&lt;br /&gt;
====2つ目の入力を追加する====&lt;br /&gt;
*華氏の入力を追加し同期させる&lt;br /&gt;
*[[React]]でstateを共有するには、共通の祖先に移動させることで実現でき、「状態の持ち上げ」という&lt;br /&gt;
*TempratureInputのローカルstateをCalcuratorへ移動させる&lt;br /&gt;
*Calucratorの共有stateは、「真の情報源」となる&lt;br /&gt;
*TempratureInputにとって、tempuratureがローカルの場合、propsは読み取り専用となるので、this.setState()とするしかないが、tempratureが、親のpropsなので、管理する必要はなくなる。&lt;br /&gt;
 const scaleName = {&lt;br /&gt;
   c: '摂氏',&lt;br /&gt;
   f: '華氏'&lt;br /&gt;
 };&lt;br /&gt;
 function BoilingVerdict(props) {&lt;br /&gt;
   if (props.celsius &amp;amp;gt;= 100) {&lt;br /&gt;
     return &amp;amp;lt;p&amp;amp;gt;The water would boil.&amp;amp;lt;/p&amp;amp;gt;;&lt;br /&gt;
   }&lt;br /&gt;
   return &amp;amp;lt;p&amp;amp;gt;The water would not boil.&amp;amp;lt;/p&amp;amp;gt;&lt;br /&gt;
 }&lt;br /&gt;
 function toCelsius(fahrenheit) {&lt;br /&gt;
   return (fahrenheit - 32) * 5/9;&lt;br /&gt;
 }&lt;br /&gt;
 function toFahrenheit(celsius) {&lt;br /&gt;
   return (celsius * 9/5) + 32;&lt;br /&gt;
 }&lt;br /&gt;
 function tryConvert(temprature, convert) {&lt;br /&gt;
   const input = parseFloat(temprature);&lt;br /&gt;
   if (Number.isNaN(input)) {&lt;br /&gt;
     return '';&lt;br /&gt;
   }&lt;br /&gt;
   const output = convert(input);&lt;br /&gt;
   const rounded = Math.round(output * 1000) / 1000;&lt;br /&gt;
   return rounded.toString();&lt;br /&gt;
 }&lt;br /&gt;
 class TempratureInput extends [[React]].Component {&lt;br /&gt;
   constructor(props) {&lt;br /&gt;
     super(props);&lt;br /&gt;
     this.handleChange = this.handleChange.bind(this);&lt;br /&gt;
     this.state = {temprature: ''};&lt;br /&gt;
   }&lt;br /&gt;
   handleChange(e){&lt;br /&gt;
     // before:this.setState({temprature: e.target.value});&lt;br /&gt;
     this.props.onTempratureChange(e.target.value);&lt;br /&gt;
   }&lt;br /&gt;
   render(){&lt;br /&gt;
     // before:const temprature = this.state.temprature;&lt;br /&gt;
     const temprature = this.props.temprature;&lt;br /&gt;
     const scale = this.props.scale;&lt;br /&gt;
     return (&lt;br /&gt;
       &amp;amp;lt;fieldset&amp;amp;gt;&lt;br /&gt;
         &amp;amp;lt;legend&amp;amp;gt;Enter temprature in {scaleName[scale]}:&amp;amp;lt;/legend&amp;amp;gt;&lt;br /&gt;
         &amp;amp;lt;input value={temprature} onChange={this.handleChange} /&amp;amp;gt;&lt;br /&gt;
         &amp;amp;lt;BoilingVerdict celsius={parseFloat(temprature)} /&amp;amp;gt;  &lt;br /&gt;
       &amp;amp;lt;/fieldset&amp;amp;gt;&lt;br /&gt;
     );&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
 class Calculator extends [[React]].Component {&lt;br /&gt;
   constructor(props) {&lt;br /&gt;
     super(props);&lt;br /&gt;
     this.handleCelsiumChange = this.handleCelsiumChange.bind(this);&lt;br /&gt;
     this.handlFahrenheitChange = this.handlFahrenheitChange.bind(this);&lt;br /&gt;
     this.state = {scale:'c', temprature:''};&lt;br /&gt;
   }&lt;br /&gt;
   handleCelsiumChange(temprature) {&lt;br /&gt;
     this.setState({scale:'c', temprature});&lt;br /&gt;
   }&lt;br /&gt;
   handlFahrenheitChange(temprature) {&lt;br /&gt;
     this.setState({scale:'f', temprature});&lt;br /&gt;
   }&lt;br /&gt;
   render() {&lt;br /&gt;
     const scale = this.state.scale;&lt;br /&gt;
     const temprature = this.state.temprature;&lt;br /&gt;
     const celsius = scale == 'f' ? tryConvert(temprature, toCelsius) : temprature;&lt;br /&gt;
     const fahrenheit = scale == 'c' ? tryConvert(temprature, toFahrenheit) : temprature;&lt;br /&gt;
     return (&lt;br /&gt;
       &amp;amp;lt;div&amp;amp;gt;&lt;br /&gt;
         &amp;amp;lt;TempratureInput scale=&amp;quot;c&amp;quot; temprature={celsius} onTempratureChange={this.handleCelsiumChange} /&amp;amp;gt;&lt;br /&gt;
         &amp;amp;lt;TempratureInput scale=&amp;quot;f&amp;quot; temprature={fahrenheit} onTempratureChange={this.handlFahrenheitChange}/&amp;amp;gt;&lt;br /&gt;
         &amp;amp;lt;BoilingVerdict celsius={parseFloat(celsius)} /&amp;amp;gt;&lt;br /&gt;
       &amp;amp;lt;/div&amp;amp;gt;&lt;br /&gt;
     );&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
 [[React]]DOM.render(&lt;br /&gt;
   &amp;amp;lt;div&amp;amp;gt;&lt;br /&gt;
     &amp;amp;lt;Calculator /&amp;amp;gt;&lt;br /&gt;
   &amp;amp;lt;/div&amp;amp;gt;,&lt;br /&gt;
   document.getElementById('root')&lt;br /&gt;
 );&lt;br /&gt;
[[File:1100_react15.jpg]]&lt;br /&gt;
===コンポジションと継承===&lt;br /&gt;
*[[React]]は強力なコンポジションモデルをもつ。コンポーネントの再利用には継承よりコンポジションを推奨する&lt;br /&gt;
====封じ込める====&lt;br /&gt;
*一部のコンポーネントは自身の子供を事前に知ることができない&lt;br /&gt;
*これは、特にサイドバーやダイアログなどボックスを表現するコンポーネント共通&lt;br /&gt;
*このようなコンポーネントには特別な子供propを使用し直接その要素に出力する&lt;br /&gt;
*&amp;amp;lt;FancyBorder&amp;amp;gt;の内側に何があっても、JSXタグはFancyBorderコンポーネントをprops.children として経由する&lt;br /&gt;
 &amp;amp;lt;style type=&amp;quot;text/css&amp;quot;&amp;amp;gt;&lt;br /&gt;
   div.FancyBorder {&lt;br /&gt;
     border : 2px dashed;&lt;br /&gt;
   }&lt;br /&gt;
   div.FancyBorder-blue {&lt;br /&gt;
     border-color: blue;&lt;br /&gt;
   }&lt;br /&gt;
 &amp;amp;lt;/style&amp;amp;gt;&lt;br /&gt;
&lt;br /&gt;
 function FancyBorder(props) {&lt;br /&gt;
   return (&lt;br /&gt;
     &amp;amp;lt;div className={'FancyBorder FancyBorder-' + props.color}&amp;amp;gt;&lt;br /&gt;
       {props.children}&lt;br /&gt;
     &amp;amp;lt;/div&amp;amp;gt;&lt;br /&gt;
   );&lt;br /&gt;
 }&lt;br /&gt;
 function WelcomDialog() {&lt;br /&gt;
   return (&lt;br /&gt;
     &amp;amp;lt;FancyBorder color=&amp;quot;blue&amp;quot;&amp;amp;gt;&lt;br /&gt;
       &amp;amp;lt;h1 className=&amp;quot;Dialog-title&amp;quot;&amp;amp;gt;Welcome&amp;amp;lt;/h1&amp;amp;gt;&lt;br /&gt;
     &amp;amp;lt;/FancyBorder&amp;amp;gt;&lt;br /&gt;
   );&lt;br /&gt;
 }&lt;br /&gt;
 [[React]]DOM.render(&lt;br /&gt;
   &amp;amp;lt;div&amp;amp;gt;&lt;br /&gt;
     &amp;amp;lt;WelcomDialog /&amp;amp;gt;&lt;br /&gt;
   &amp;amp;lt;/div&amp;amp;gt;,&lt;br /&gt;
   document.getElementById('root')&lt;br /&gt;
 );&lt;br /&gt;
[[File:1101_react16.jpg]]&lt;br /&gt;
====特殊化====&lt;br /&gt;
*コンポーネントを他のコンポーネントの特殊なものとして考えることがある、例えば、WelcomDialogはDialogの特殊な例として。&lt;br /&gt;
*[[React]]では、コンポジションを使って実現する&lt;br /&gt;
*クラスを用いても同様に記述できる&lt;br /&gt;
 function Dialog(props) {&lt;br /&gt;
   return (&lt;br /&gt;
     &amp;amp;lt;FancyBorder color=&amp;quot;blue&amp;quot;&amp;amp;gt;&lt;br /&gt;
       &amp;amp;lt;h1 className=&amp;quot;Dialog-title&amp;quot;&amp;amp;gt;{props.title}&amp;amp;lt;/h1&amp;amp;gt;&lt;br /&gt;
     &amp;amp;lt;/FancyBorder&amp;amp;gt;&lt;br /&gt;
   );&lt;br /&gt;
 }&lt;br /&gt;
 function FancyBorder(props) {&lt;br /&gt;
   return (&lt;br /&gt;
     &amp;amp;lt;div className={'FancyBorder FancyBorder-' + props.color}&amp;amp;gt;&lt;br /&gt;
       {props.children}&lt;br /&gt;
     &amp;amp;lt;/div&amp;amp;gt;&lt;br /&gt;
   );&lt;br /&gt;
 }&lt;br /&gt;
 function WelcomDialog() {&lt;br /&gt;
   return (&lt;br /&gt;
     &amp;amp;lt;Dialog title=&amp;quot;Welcome&amp;quot; /&amp;amp;gt;&lt;br /&gt;
   );&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
===[[React Router]]===&lt;br /&gt;
*[[React Router]]&lt;br /&gt;
===[[Redux]]===&lt;br /&gt;
*[[Redux]]&lt;br /&gt;
===[[Tips]]===&lt;br /&gt;
*[http://typea.info/blg/glob/2017/06/react.html React のシンタックスエラーをデバッグ]&lt;br /&gt;
&lt;br /&gt;
{{ref example.zip}}&lt;br /&gt;
====ビルド====&lt;br /&gt;
*https://mae.chab.in/archives/2765&lt;br /&gt;
*https://mae.chab.in/archives/2891&lt;/div&gt;</summary>
		<author><name>Piroto</name></author>
		
	</entry>
	<entry>
		<id>https://www.typea.info/tips_/index.php?title=React&amp;diff=35329</id>
		<title>React</title>
		<link rel="alternate" type="text/html" href="https://www.typea.info/tips_/index.php?title=React&amp;diff=35329"/>
		<updated>2024-10-05T08:34:56Z</updated>

		<summary type="html">&lt;p&gt;Piroto: /* ファイル拡張子 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==[[React]]==&lt;br /&gt;
[[Node.js]] | [[Next.js]] |&lt;br /&gt;
&lt;br /&gt;
{{amazon|4873117887}}&lt;br /&gt;
&lt;br /&gt;
{{amazon|4815619484}}&lt;br /&gt;
&lt;br /&gt;
===スケルトン作成===&lt;br /&gt;
#[https://www.typea.info/blog/index.php/2017/08/15/react_1/ 開発の全体像を把握しつつ開発環境を整える]&lt;br /&gt;
#[https://www.typea.info/blog/index.php/2017/08/16/react_router/ React の単純なサンプルに React Router を適用する]&lt;br /&gt;
#[https://www.typea.info/blog/index.php/2017/08/17/react_react_router_redux-saga/ React の単純なサンプルに React Router を組み込んだものに Redux-Saga を適用する]&lt;br /&gt;
#[https://www.typea.info/blog/index.php/2017/08/19/react_react_router_redux-saga_ajax/ React の単純なサンプルに React Router を組み込んだものに Redux-Saga を適用したものからAjax通信を組み込む]&lt;br /&gt;
#[https://www.typea.info/blog/index.php/2017/08/23/react-react_router-redux-saga-superagent_bootstrap/ React環境-&amp;amp;gt;React Router-&amp;amp;gt;Redux-Saga-&amp;amp;gt;SuperAgent に Bootstrapを適用する]&lt;br /&gt;
&lt;br /&gt;
==導入==&lt;br /&gt;
&lt;br /&gt;
===Create React App===&lt;br /&gt;
*Reactアプリ開発のためのコマンドラインツール。トランスパイラ、バンドラ、開発サーバーなどを含むツールチェーン&lt;br /&gt;
*Facebook本家が提供。他にもNext.js、Vite、Gatsby、Parcelなどのツールチェーンがある。&lt;br /&gt;
*より高度な環境としてNext.jsも存在&lt;br /&gt;
&lt;br /&gt;
===Next.js===&lt;br /&gt;
*[[Next.js]]&lt;br /&gt;
*Reactは、あくまでUI部分のみ&lt;br /&gt;
*本格的なアプリ開発には周辺領域を担うためのフレームワークが必要&lt;br /&gt;
*Reactベースのフレームワークとしてデファクトスタンダードと言える存在&lt;br /&gt;
*主なライブラリ&lt;br /&gt;
**ファイルシステムベースの設定レスルーター&lt;br /&gt;
**サーバーコンポーネント&lt;br /&gt;
**データ取得用fetchメソッド&lt;br /&gt;
**リソース組み込みの自動最適化&lt;br /&gt;
**CSSフレームワーク、Tailwind　CSSへの標準対応&lt;br /&gt;
&lt;br /&gt;
===Node===&lt;br /&gt;
[[Node.js]] のインストール&lt;br /&gt;
&lt;br /&gt;
====npx====&lt;br /&gt;
*ローカルにインストールされたツールを実行するためのパッケージランナー&lt;br /&gt;
&lt;br /&gt;
===Next.jsアプリの作成===&lt;br /&gt;
[[Next.js]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===[[TypeScript]]の導入===&lt;br /&gt;
====ファイル拡張子====&lt;br /&gt;
*https://3chome.net/javascript-typescript/#:~:text=.tsx%EF%BC%88TSX%E3%83%95%E3%82%A1&lt;br /&gt;
*TypeScriptの拡張子は、.ts、.tsx&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===導入(旧)===&lt;br /&gt;
----&lt;br /&gt;
*https://facebook.github.io/react/docs/installation.html&lt;br /&gt;
*https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/[[R]]EADME.md#table-of-contents&lt;br /&gt;
*[[React]]のSPAを作成するのによい方法&lt;br /&gt;
 [[npm]] install -g create-react-app&lt;br /&gt;
*https://ja.reactjs.org/docs/create-a-new-react-app.html&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
npx create-react-app my-app&lt;br /&gt;
cd my-app&lt;br /&gt;
npm start&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
*[[React]]はバックエンドロジックやデータベースを持たないが、使いたいものを使えばよい。&lt;br /&gt;
*Babelやwebpackのようなビルドツールも設定なしに利用できる。&lt;br /&gt;
 PS C:\workspaces\vscode\reactlesson&amp;amp;gt; create-react-app react-lesson&lt;br /&gt;
 Creating a new [[React]] app in C:\workspaces\vscode\reactlesson\react-lesson.&lt;br /&gt;
 &lt;br /&gt;
 Installing packages. This might take a couple minutes.&lt;br /&gt;
 Installing react, react-dom, and react-scripts...&lt;br /&gt;
               :&lt;br /&gt;
*アプリケーションが作成されたら実行&lt;br /&gt;
 PS C:\workspaces\vscode\reactlesson&amp;amp;gt; cd react-lesson&lt;br /&gt;
 PS C:\workspaces\vscode\reactlesson&amp;amp;gt; [[npm]] start&lt;br /&gt;
*実行された&lt;br /&gt;
[[File:1086_react01.jpg]]&lt;br /&gt;
*/src/App.js を書き換えてみる&lt;br /&gt;
 import [[React]], { Component } from 'react';&lt;br /&gt;
 import logo from './logo.svg';&lt;br /&gt;
 import './App.css';&lt;br /&gt;
 &lt;br /&gt;
 const element = (&amp;amp;lt;h1&amp;amp;gt;Hello,world&amp;amp;lt;/h1&amp;amp;gt;);&lt;br /&gt;
 class App extends Component {&lt;br /&gt;
   render() {&lt;br /&gt;
     return (&lt;br /&gt;
       element&lt;br /&gt;
     );&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 export default App;&lt;br /&gt;
*反映された&lt;br /&gt;
[[File:1087_react02.jpg]]&lt;br /&gt;
*リリース準備ができたら、以下を実行することで、buildフォルダ以下に最適化されたアプリケーションを作成する&lt;br /&gt;
 [[npm]] run build&lt;br /&gt;
&lt;br /&gt;
==クイックスタート==&lt;br /&gt;
===JSX===&lt;br /&gt;
 const element = &amp;amp;lt;h1&amp;amp;gt;Hello,world!&amp;amp;lt;/h1&amp;amp;gt;;&lt;br /&gt;
*文字列でも、[[HTML]]でもなく、JSX&lt;br /&gt;
*[[JavaScript]]の拡張文法&lt;br /&gt;
*テンプレートと思われるかもしれないが、完全な[[JavaScript]]&lt;br /&gt;
*JSXは[[React]]の要素を生成する&lt;br /&gt;
===JSX表現===&lt;br /&gt;
*どのような[[JavaScript]]の表現も、中括弧で囲むことでJSXに埋め込むことができる&lt;br /&gt;
*const element = (&amp;amp;lt;h1&amp;amp;gt;Hello, {formatName(user)}!&amp;amp;lt;/h1&amp;amp;gt;);&lt;br /&gt;
&lt;br /&gt;
 &amp;amp;lt;!DOCTYPE html&amp;amp;gt;&lt;br /&gt;
 &amp;amp;lt;html&amp;amp;gt;&lt;br /&gt;
   &amp;amp;lt;head&amp;amp;gt;&lt;br /&gt;
     &amp;amp;lt;meta charset=&amp;quot;UTF-8&amp;quot; /&amp;amp;gt;&lt;br /&gt;
     &amp;amp;lt;title&amp;amp;gt;Hello World&amp;amp;lt;/title&amp;amp;gt;&lt;br /&gt;
     &amp;amp;lt;script src=&amp;quot;https://unpkg.com/react@latest/dist/react.js&amp;quot;&amp;amp;gt;&amp;amp;lt;/script&amp;amp;gt;&lt;br /&gt;
     &amp;amp;lt;script src=&amp;quot;https://unpkg.com/react-dom@latest/dist/react-dom.js&amp;quot;&amp;amp;gt;&amp;amp;lt;/script&amp;amp;gt;&lt;br /&gt;
     &amp;amp;lt;script src=&amp;quot;https://unpkg.com/babel-standalone@6.15.0/babel.min.js&amp;quot;&amp;amp;gt;&amp;amp;lt;/script&amp;amp;gt;&lt;br /&gt;
   &amp;amp;lt;/head&amp;amp;gt;&lt;br /&gt;
   &amp;amp;lt;body&amp;amp;gt;&lt;br /&gt;
     &amp;amp;lt;div id=&amp;quot;root&amp;quot;&amp;amp;gt;&amp;amp;lt;/div&amp;amp;gt;&lt;br /&gt;
     &amp;amp;lt;script type=&amp;quot;text/babel&amp;quot;&amp;amp;gt;&lt;br /&gt;
     function formatName(user) {&lt;br /&gt;
         return user.firstName + ' ' + user.lastName;&lt;br /&gt;
     }&lt;br /&gt;
     const user = {firstName:'Hiroto', lastName:'Yagi'};&lt;br /&gt;
     const element = (&amp;amp;lt;h1&amp;amp;gt;Hello, {formatName(user)}!&amp;amp;lt;/h1&amp;amp;gt;); &lt;br /&gt;
     [[React]]DOM.render(&lt;br /&gt;
         element,&lt;br /&gt;
         document.getElementById('root')&lt;br /&gt;
     );&lt;br /&gt;
     &amp;amp;lt;/script&amp;amp;gt;&lt;br /&gt;
   &amp;amp;lt;/body&amp;amp;gt;&lt;br /&gt;
 &amp;amp;lt;/html&amp;amp;gt;&lt;br /&gt;
&lt;br /&gt;
*コンパイルされたJSXは通常の[[JavaScript]]オブジェクト&lt;br /&gt;
*JSXをif文やforループ、変数への割り当て、引数や戻り値に利用できる&lt;br /&gt;
&lt;br /&gt;
 function greeting(user) {&lt;br /&gt;
    var now = new Date();&lt;br /&gt;
    if (5 &amp;amp;lt;= now.getHours() &amp;amp;&amp;amp; now.getHours() &amp;amp;lt;= 12) {&lt;br /&gt;
        return &amp;amp;lt;h1&amp;amp;gt; Good morning {user.firstName + ' ' + user.lastName}.&amp;amp;lt;/h1&amp;amp;gt;;&lt;br /&gt;
    } else {&lt;br /&gt;
        return &amp;amp;lt;h1&amp;amp;gt; Hello {user.firstName + ' ' + user.lastName}.&amp;amp;lt;/h1&amp;amp;gt;;&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
====属性に利用====&lt;br /&gt;
*中括弧を利用して、二重引用符なし(使用すると文字列リテラルとして扱われる)で直接利用できる。&lt;br /&gt;
 &amp;amp;lt;div id=&amp;quot;root&amp;quot;&amp;amp;gt;&amp;amp;lt;/div&amp;amp;gt;&lt;br /&gt;
 &amp;amp;lt;script type=&amp;quot;text/babel&amp;quot;&amp;amp;gt;&lt;br /&gt;
 function greeting(user) {&lt;br /&gt;
     var now = new Date();&lt;br /&gt;
     if (5 &amp;amp;lt;= now.getHours() &amp;amp;&amp;amp; now.getHours() &amp;amp;lt;= 12) {&lt;br /&gt;
         return &amp;amp;lt;h1&amp;amp;gt; Good morning &amp;amp;lt;a href={user.webpageUrl}&amp;amp;gt;{user.firstName + ' ' + user.lastName}&amp;amp;lt;/a&amp;amp;gt;.&amp;amp;lt;/h1&amp;amp;gt;;&lt;br /&gt;
     } else {&lt;br /&gt;
         return &amp;amp;lt;h1&amp;amp;gt; Hello &amp;amp;lt;a href={user.webpageUrl}&amp;amp;gt;{user.firstName + ' ' + user.lastName}&amp;amp;lt;/a&amp;amp;gt;.&amp;amp;lt;/h1&amp;amp;gt;;&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
 const user = {firstName:'Hiroto', lastName:'Yagi', webpageUrl:'http://typea.info'};&lt;br /&gt;
 const element = (&amp;amp;lt;h1&amp;amp;gt;{greeting(user)}&amp;amp;lt;/h1&amp;amp;gt;); &lt;br /&gt;
 [[React]]DOM.render(&lt;br /&gt;
     element,&lt;br /&gt;
     document.getElementById('root')&lt;br /&gt;
 );&lt;br /&gt;
[[File:1089_react04.jpg]]&lt;br /&gt;
====子要素====&lt;br /&gt;
*子要素がない場合、[[XML]]同様　/&amp;amp;gt; で閉じる&lt;br /&gt;
*子要素を含む&lt;br /&gt;
*JSXはHTMLより[[JavaScript]]により近い。ReactDOMはキャメルケースプロパティ(HTMLでは、class がclassName、HTMLではtabindexがtabIndexなど)を持つ&lt;br /&gt;
 function greeting(user) {&lt;br /&gt;
     return &amp;amp;lt;div&amp;amp;gt;&lt;br /&gt;
             &amp;amp;lt;h1&amp;amp;gt; Good morning {user.firstName + ' ' + user.lastName}.&amp;amp;lt;/h1&amp;amp;gt;&lt;br /&gt;
             &amp;amp;lt;h2&amp;amp;gt;&amp;amp;lt;a href={user.webpageUrl}&amp;amp;gt;webpage&amp;amp;lt;/a&amp;amp;gt;&amp;amp;lt;/h2&amp;amp;gt;&lt;br /&gt;
            &amp;amp;lt;/div&amp;amp;gt;&lt;br /&gt;
            ;&lt;br /&gt;
 }&lt;br /&gt;
 const user = {firstName:'Hiroto', lastName:'Yagi', webpageUrl:'http://typea.info'};&lt;br /&gt;
 const element = (greeting(user)); &lt;br /&gt;
 [[React]]DOM.render(&lt;br /&gt;
     element,&lt;br /&gt;
     document.getElementById('root')&lt;br /&gt;
 );&lt;br /&gt;
[[File:1090_react05.jpg]]&lt;br /&gt;
====インジェクション[[攻撃]]の予防====&lt;br /&gt;
*デフォルトで[[React]] DOMは、JSXに埋め込まれた値をレンダリング前にエスケープする&lt;br /&gt;
*明示的にアプリケーションに記述しなくてもインジェクションされないことを保証する&lt;br /&gt;
*XSS[[攻撃]]の予防を助ける&lt;br /&gt;
 function greeting(user, title) {&lt;br /&gt;
     return &amp;amp;lt;div&amp;amp;gt;&lt;br /&gt;
              &amp;amp;lt;h1&amp;amp;gt;{title}&amp;amp;lt;/h1&amp;amp;gt;&lt;br /&gt;
              &amp;amp;lt;h2&amp;amp;gt; Good morning {user.firstName + ' ' + user.lastName}.&amp;amp;lt;/h2&amp;amp;gt;&lt;br /&gt;
              &amp;amp;lt;h2&amp;amp;gt;&amp;amp;lt;a href={user.webpageUrl}&amp;amp;gt;webpage&amp;amp;lt;/a&amp;amp;gt;&amp;amp;lt;/h2&amp;amp;gt;&lt;br /&gt;
            &amp;amp;lt;/div&amp;amp;gt;&lt;br /&gt;
            ;&lt;br /&gt;
 }&lt;br /&gt;
 const title = &amp;quot;&amp;amp;lt;input type='button'&amp;amp;gt;&amp;quot;;&lt;br /&gt;
 const user = {firstName:'Hiroto', lastName:'Yagi', webpageUrl:'http://typea.info'};&lt;br /&gt;
 const element = (greeting(user,title)); &lt;br /&gt;
 [[React]]DOM.render(&lt;br /&gt;
     element,&lt;br /&gt;
     document.getElementById('root')&lt;br /&gt;
 );&lt;br /&gt;
[[File:1091_react06.jpg]]&lt;br /&gt;
====JSX [[R]]epresent オブジェクト====&lt;br /&gt;
*Babelは、[[React]].createElement()を呼び出しコンパイルを行う&lt;br /&gt;
*以下の2つは同じ意味&lt;br /&gt;
 const element1 = (&amp;amp;lt;h1 className='greeting'&amp;amp;gt;hello&amp;amp;lt;/h1&amp;amp;gt;);&lt;br /&gt;
 const element2 = [[React]].createElement('h1',{className:'greeting'},'hello');&lt;br /&gt;
*[[React]].createElement()は、バグを防ぐ手助けをするが、本質的には以下のようなオブジェクトを生成する&lt;br /&gt;
 // 簡易表現&lt;br /&gt;
 const element = {type:'h1',props:{className:'greeting',children:'hello'}};&lt;br /&gt;
*これらの要素を&amp;quot;[[React]] elements&amp;quot;と呼ぶ&lt;br /&gt;
*画面に表示させたいものの記述と考えることができる&lt;br /&gt;
*[[React]]はこれらのオブジェクトを読み、DOMの構築と最新化に利用する    &lt;br /&gt;
===Elementsのレンダリング===&lt;br /&gt;
*Elements は[[React]] アプリケーションの最小のビルディングブロック&lt;br /&gt;
*1つの要素は、画面上に表示するものを表現する&lt;br /&gt;
*ブラウザのDOM要素と異なり、[[React]] Elements はプレーンなオブジェクトで生成のコストは小さい&lt;br /&gt;
*[[React]] DOMは、DOMを[[React]] Elementsに一致するように取り扱う&lt;br /&gt;
====1つの要素を[[DOM]]の中にレンダリング====&lt;br /&gt;
*[[HTML]]どこかに記述する、以下のDIV要素をroot DOM ノードと呼ぶ&lt;br /&gt;
*[[React]] DOM が管理するすべてが、この要素の中にある&lt;br /&gt;
 &amp;amp;lt;div id=&amp;quot;root&amp;quot;&amp;amp;gt;&amp;amp;lt;/div&amp;amp;gt;&lt;br /&gt;
====[[React]]要素の更新====&lt;br /&gt;
*[[React]]要素は不変。一旦生成したら、子要素、属性などは変更できない。&lt;br /&gt;
*UIを更新するには、新しい要素を作成し、[[React]]DOM.rendar()に引き渡す。&lt;br /&gt;
 function tick() {&lt;br /&gt;
   const element = (&amp;amp;lt;div&amp;amp;gt;{(new Date()).toLocaleTimeString()}&amp;amp;lt;/div&amp;amp;gt;);&lt;br /&gt;
   [[React]]DOM.render(&lt;br /&gt;
       element,&lt;br /&gt;
       document.getElementById('root')&lt;br /&gt;
   );&lt;br /&gt;
 }&lt;br /&gt;
 setInterval(tick,1000);&lt;br /&gt;
[[File:1092_react07.jpg]]&lt;br /&gt;
&amp;amp;lt;blockquote&amp;amp;gt;通常の[[React]] アプリケーションでは、[[React]]DOM.rendar()は 一度しか呼びださない。&amp;amp;lt;/blockquote&amp;amp;gt;&lt;br /&gt;
====[[React]]は必要なもののみ更新する====&lt;br /&gt;
*[[React]] DOMは、要素および子要素を前の状態と比較し、DOMの更新が必要な個所にのみ適用する。&lt;br /&gt;
*ブラウザツールで、上記のソースコードを確認する&lt;br /&gt;
[[File:1093_react08.jpg]]&lt;br /&gt;
&amp;amp;lt;blockquote&amp;amp;gt;毎tick()の呼び出しで、すべてのUIツリーを生成するよう記述してるが、変更が発生したテキストノードのみ[[React]] DOMにより更新されている。&amp;amp;lt;/blockquote&amp;amp;gt;&lt;br /&gt;
===コンポーネントと Props===&lt;br /&gt;
*コンポーネントはUIを独立し再利用可能な部分に分割する。&lt;br /&gt;
*概念的にコンポーネントは[[JavaScript]]の関数のようなもの。&lt;br /&gt;
*コンポーネントはpropsと呼ばれる任意の入力を受け付け、[[React]] Elementを返す。&lt;br /&gt;
====コンポーネントの機能とクラス====&lt;br /&gt;
*[[JavaScript]]の関数としてコンポーネントを定義する&lt;br /&gt;
*この関数は有効な[[React]]コンポーネント、なぜなら、単一のprops引数を引数として取り、[[React]] Elementを返す。&lt;br /&gt;
*このようなコンポーネントを&amp;quot;functional&amp;quot;と呼ぶ。&lt;br /&gt;
 function Welcome(props) {&lt;br /&gt;
     return &amp;amp;lt;h1&amp;amp;gt;Hello,{props.name}&amp;amp;lt;/h1&amp;amp;gt;;&lt;br /&gt;
 }&lt;br /&gt;
*ES6のクラスをコンポーネントの定義として利用できる&lt;br /&gt;
 class Welcome extends [[React]].Component {&lt;br /&gt;
     render() {&lt;br /&gt;
         return &amp;amp;lt;h1&amp;amp;gt;Hello,{props.name}&amp;amp;lt;/h1&amp;amp;gt;;&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
*上記2つのコンポーネントは[[React]]の視点からは同じ&lt;br /&gt;
====コンポーネントのレンダリング====&lt;br /&gt;
*Elementは、ユーザー定義コンポーネントも表すことができる&lt;br /&gt;
 function Welcome(props) {&lt;br /&gt;
  return &amp;amp;lt;h1&amp;amp;gt;Hello,{props.name}&amp;amp;lt;/h1&amp;amp;gt;;&lt;br /&gt;
 }&lt;br /&gt;
 const element = &amp;amp;lt;Welcome name='Hiroto' /&amp;amp;gt;&lt;br /&gt;
 [[React]]DOM.render(&lt;br /&gt;
     element,&lt;br /&gt;
     document.getElementById('root')&lt;br /&gt;
 );&lt;br /&gt;
*[[React]]がユーザー定義コンポーネントを表示するときに、JSXの属性からコンポーネントへ&amp;quot;props&amp;quot;としてオブジェクトが渡される。&lt;br /&gt;
&lt;br /&gt;
&amp;amp;lt;blockquote&amp;amp;gt;コンポーネント名はいつも大文字から始める。[[DOM]] タグは、&amp;amp;lt;div /&amp;amp;gt; だが、&amp;amp;lt;Welcome /&amp;amp;gt; はコンポーネントを表現する。Welcomeがスコープに存在すること。&amp;amp;lt;/blockquote&amp;amp;gt;&lt;br /&gt;
====コンポーネントの構成====&lt;br /&gt;
*コンポーネントはその出力において、他のコンポーネントに影響を与えることができる&lt;br /&gt;
*同じコンポーネントをどんなレベルの詳細にも抽象的に利用できる、ボタン、フォーム、ダイアログ、スクリーン&lt;br /&gt;
*[[React]]でこれらは、一般にコンポーネントで表現される&lt;br /&gt;
 function Welcome(props) {&lt;br /&gt;
   return &amp;amp;lt;h1&amp;amp;gt;Hello,{props.name}&amp;amp;lt;/h1&amp;amp;gt;;&lt;br /&gt;
 }&lt;br /&gt;
 function App() {&lt;br /&gt;
   return ( &amp;amp;lt;div&amp;amp;gt;&lt;br /&gt;
       &amp;amp;lt;Welcome name=&amp;quot;Yagi&amp;quot;/&amp;amp;gt;&lt;br /&gt;
       &amp;amp;lt;Welcome name=&amp;quot;Kaela&amp;quot;/&amp;amp;gt;&lt;br /&gt;
       &amp;amp;lt;Welcome name=&amp;quot;Hiroto&amp;quot;/&amp;amp;gt;&lt;br /&gt;
     &amp;amp;lt;/div&amp;amp;gt; );&lt;br /&gt;
 }&lt;br /&gt;
 [[React]]DOM.render(&lt;br /&gt;
     &amp;amp;lt;App /&amp;amp;gt;,&lt;br /&gt;
     document.getElementById('root')&lt;br /&gt;
 );&lt;br /&gt;
*一般的に新しい[[React]]アプリケーションは、一つのAppコンポーネントを最上位に持つ。既存のアプリケーションに[[React]]を統合する場合は、小さなコンポーネント、例えばButtonなど、ボトムアップから開始し、徐々にView階層の最上位にいたる。&lt;br /&gt;
&lt;br /&gt;
&amp;amp;lt;blockquote&amp;amp;gt;コンポーネントは、一つのroot要素を返さなければならない。上記で、Welcome要素を div に含めたのはこのため&amp;amp;lt;/blockquote&amp;amp;gt;&lt;br /&gt;
====Propsは読み取り専用====&lt;br /&gt;
**[[React]]はかなりフレキシブルだが、1つ厳格なルールがある。function だろうと class だろうとコンポーネントはpropsを編集できない。&lt;br /&gt;
===状態とライフサイクル===&lt;br /&gt;
*次のClockコンポーネントを再利用可能にカプセル化する&lt;br /&gt;
 function Clock(props) {&lt;br /&gt;
   return (&lt;br /&gt;
     &amp;amp;lt;div&amp;amp;gt;&lt;br /&gt;
       &amp;amp;lt;h2&amp;amp;gt;{props.date.toLocaleTimeString()}&amp;amp;lt;/h2&amp;amp;gt;&lt;br /&gt;
     &amp;amp;lt;/div&amp;amp;gt;&lt;br /&gt;
   );&lt;br /&gt;
 }&lt;br /&gt;
 function tick() {&lt;br /&gt;
   [[React]]DOM.render(&lt;br /&gt;
       &amp;amp;lt;Clock date={new Date()} /&amp;amp;gt;,&lt;br /&gt;
       document.getElementById('root')&lt;br /&gt;
   );&lt;br /&gt;
 }&lt;br /&gt;
 setInterval(tick, 1000);&lt;br /&gt;
&lt;br /&gt;
[[File:1094_react09.jpg]]&lt;br /&gt;
&lt;br /&gt;
*実装のために、Clockコンポーネントにstateを追加する。&lt;br /&gt;
*状態は、propsと同様だが、private かつ、コンポーネントから完全に制御される&lt;br /&gt;
*クラス宣言したコンポーネントにはいくつかの追加的な機能があるが、local state はこれにあたる&lt;br /&gt;
====関数をクラスに変更する====&lt;br /&gt;
#[[React]].Component を継承して同名のES6クラスを作成する&lt;br /&gt;
#render()メソッドを作成し、処理を移動、functionを削除&lt;br /&gt;
#propsをthis.propsに変更&lt;br /&gt;
 class Clock extends [[React]].Component {&lt;br /&gt;
   render() {&lt;br /&gt;
     return (&lt;br /&gt;
       &amp;amp;lt;div&amp;amp;gt;&lt;br /&gt;
         &amp;amp;lt;h2&amp;amp;gt;{this.props.date.toLocaleTimeString()}&amp;amp;lt;/h2&amp;amp;gt;&lt;br /&gt;
       &amp;amp;lt;/div&amp;amp;gt;&lt;br /&gt;
     );&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
====クラスにローカル状態を追加する====&lt;br /&gt;
*date を props から state へ移動する&lt;br /&gt;
#render()メソッドの中の、this.props.date を this.state.date に変更&lt;br /&gt;
#クラスにコンストラクタを追加し、this.stateの初期状態を記述する&lt;br /&gt;
#&amp;amp;lt;Clock date={new Date()} /&amp;amp;gt; から dateを削除&lt;br /&gt;
 class Clock extends [[React]].Component {&lt;br /&gt;
   constructor(props) {&lt;br /&gt;
     super(props);&lt;br /&gt;
     this.state = {date : new Date()};&lt;br /&gt;
   }&lt;br /&gt;
   render() {&lt;br /&gt;
     return (&lt;br /&gt;
       &amp;amp;lt;div&amp;amp;gt;&lt;br /&gt;
         &amp;amp;lt;h2&amp;amp;gt;{this.state.date.toLocaleTimeString()}&amp;amp;lt;/h2&amp;amp;gt;&lt;br /&gt;
       &amp;amp;lt;/div&amp;amp;gt;&lt;br /&gt;
     );&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
====クラスにライフサイクルメソッドを追加する====&lt;br /&gt;
*多くのコンポーネントを使用するアプリケーションでは、破棄されたコンポーネントのリソースの解放が重要&lt;br /&gt;
*ClockがDOMに最初にレンダリングされるときには、必ずタイマーをセットアップしたい。これを[[React]]では、&amp;quot;mounting&amp;quot; という&lt;br /&gt;
*また、ClockがDOMから取り除かれるときには、タイマーをクリアしたい。これを[[React]]では、&amp;quot;unmounting&amp;quot;という&lt;br /&gt;
*コンポーネントが、mount/unmount されるときに実行される特別なメソッドをクラスに宣言できる&lt;br /&gt;
*componentDidMount()、componentWillUnmount() これらのメソッドはライフサイクルフックと呼ばれる&lt;br /&gt;
*どのようにtimer IDを thisに保存するか&lt;br /&gt;
**this.propsが[[React]]によりセットアップされる間、this.stateは特別な意味を持つ&lt;br /&gt;
**表示に使用しないならば、クラスに自由にフィールドを追加できる&lt;br /&gt;
**render()の中では、それらは利用できないし、ステートも持たない&lt;br /&gt;
*最後に、毎秒実行されるtick()メソッドを実装する。&lt;br /&gt;
*this.setState()でローカルコンポーネントの状態を更新する&lt;br /&gt;
&lt;br /&gt;
 class Clock extends [[React]].Component {&lt;br /&gt;
   constructor(props) {&lt;br /&gt;
     super(props);&lt;br /&gt;
     this.state = {date : new Date()};&lt;br /&gt;
   }&lt;br /&gt;
   componentDidMount() {&lt;br /&gt;
     this.timerID = setInterval(&lt;br /&gt;
       () =&amp;amp;gt; this.tick(),1000&lt;br /&gt;
     );&lt;br /&gt;
   }&lt;br /&gt;
   componentWillUnmount() {&lt;br /&gt;
     clearInterval(this.timerID);&lt;br /&gt;
   }&lt;br /&gt;
   tick() {&lt;br /&gt;
     this.setState({&lt;br /&gt;
       date: new Date()&lt;br /&gt;
     });&lt;br /&gt;
   }&lt;br /&gt;
   render() {&lt;br /&gt;
     return (&lt;br /&gt;
       &amp;amp;lt;div&amp;amp;gt;&lt;br /&gt;
         &amp;amp;lt;h2&amp;amp;gt;{this.state.date.toLocaleTimeString()}&amp;amp;lt;/h2&amp;amp;gt;&lt;br /&gt;
       &amp;amp;lt;/div&amp;amp;gt;&lt;br /&gt;
     );&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
 [[React]]DOM.render(&lt;br /&gt;
   &amp;amp;lt;Clock /&amp;amp;gt;,&lt;br /&gt;
   document.getElementById('root')&lt;br /&gt;
 );&lt;br /&gt;
====状態を正しく使う====&lt;br /&gt;
=====stateを直接操作しない=====&lt;br /&gt;
 // まちがい&lt;br /&gt;
 this.state.comment = 'Hello';&lt;br /&gt;
*上記の代わりに、setState() を利用する&lt;br /&gt;
 // 正しい&lt;br /&gt;
 this.setSatate({comment:'Hello'});&lt;br /&gt;
&amp;amp;lt;blockquote&amp;amp;gt;this.stateを割り当てることができるのは、コンストラクタのみ&amp;amp;lt;/blockquote&amp;amp;gt;&lt;br /&gt;
=====stateは、非同期に更新される=====&lt;br /&gt;
*[[React]]は、複数のsetState() をパフォーマンスのためにまとめて一度に処理する。&lt;br /&gt;
*このため、this.propsとthis.stateは非同期に更新される&lt;br /&gt;
*これらの値を信頼して、次の状態への計算を行うべきではない&lt;br /&gt;
 // まちがい&lt;br /&gt;
 this.setState({&lt;br /&gt;
   counter: this.state.counter + this.props.increament,&lt;br /&gt;
 });&lt;br /&gt;
*修正するには、オブジェクトではなく関数を受け取る、setState()を使用する&lt;br /&gt;
*関数は、ひとつ前の状態(state)を最初の引数として、更新時のpropsを2つ目の引数として取る&lt;br /&gt;
 // 正しい&lt;br /&gt;
 this.setState((prevState, props) =&amp;amp;gt; ({&lt;br /&gt;
   counter: prevState.counter + prpos.increament&lt;br /&gt;
 }));&lt;br /&gt;
*通常の関数でもよい&lt;br /&gt;
 // 正しい&lt;br /&gt;
 this.setState(function(prevState, props) {&lt;br /&gt;
   return { counter: prevState.counter + props.increament };&lt;br /&gt;
 });&lt;br /&gt;
=====状態の更新はマージされる=====&lt;br /&gt;
*setState()を呼び出すと、[[React]]は、現在のstateに提供したオブジェクトをマージする&lt;br /&gt;
*例えば、いくつかの独立した変数を含む場合&lt;br /&gt;
 constructor(props) {&lt;br /&gt;
   super(props);&lt;br /&gt;
   this.state = {&lt;br /&gt;
     posts: []&lt;br /&gt;
     comments: []&lt;br /&gt;
   };&lt;br /&gt;
 }&lt;br /&gt;
*これらを別のsetState() で更新&lt;br /&gt;
 componentDidMount() {&lt;br /&gt;
   fetchPosts().then(response =&amp;amp;gt; { this.setState({ posts: response.posts }); });&lt;br /&gt;
   fetchComments().then(response =&amp;amp;gt; { this.setState({ commentss: response.comments }); });&lt;br /&gt;
 }&lt;br /&gt;
*マージはシャローなので、setState({comment}) は、this.state.posts を損なわずに、this.state.comments を置き換える&lt;br /&gt;
====データは下へ流れる====&lt;br /&gt;
*親だけでなく子コンポーネントも確実にステートフルかステートレスか知ることはできない。&lt;br /&gt;
*状態はしばしばローカルから呼び出されるかカプセル化されていて、他からアクセスできない。&lt;br /&gt;
*コンポーネントは、自身の状態をpropsを通して子コンポーネントに渡す&lt;br /&gt;
 &amp;amp;lt;h2&amp;amp;gt;It is {this.state.date.toLocalTimeString()}.&amp;amp;lt;/h2&amp;amp;gt;&lt;br /&gt;
*これは、ユーザー定義コンポーネントでも動作する&lt;br /&gt;
&amp;amp;lt;FormattedDate date={this.state.date} /&amp;amp;gt;&lt;br /&gt;
*FormattedDateコンポーネントは、propsにdateを受け取り、Clockの状態が何かは知らない。&lt;br /&gt;
 function FormatterDate(props) {&lt;br /&gt;
   return &amp;amp;lt;h2&amp;amp;gt;It is {props.date.toLocaleTimeString()}.&amp;amp;lt;/h2&amp;amp;gt;;&lt;br /&gt;
 }&lt;br /&gt;
*これは一般的に、トップダウン、もしくは、ユニディレクショナル データフローという&lt;br /&gt;
*状態は常に特定のコンポーネントに属する。&lt;br /&gt;
*データやUIは状態に由来し、ツリーのより下のコンポーネントにのみ影響を与えることができる&lt;br /&gt;
===イベントの処理===&lt;br /&gt;
*[[React]] 要素のイベント処理は、DOMでの処理ととても似ているが、いくつかシンタックスの差異がある。&lt;br /&gt;
**[[React]]イベントは、ロウアーケースではなく、キャメルケース&lt;br /&gt;
**JSXでは、stringではなく、関数をイベントハンドラーとして渡す。&lt;br /&gt;
&lt;br /&gt;
=====[[HTML]]=====&lt;br /&gt;
 &amp;amp;lt;button onclick=&amp;quot;test()&amp;quot; /&amp;amp;gt;&lt;br /&gt;
=====[[React]]=====&lt;br /&gt;
 &amp;amp;lt;button onClick={test} /&amp;amp;gt;&lt;br /&gt;
&lt;br /&gt;
*もう一つの違いは、[[React]]では、falseを返しデフォルトのふるまいを防止することができない。&lt;br /&gt;
*明示的に、preventDefault を呼び出す必要がある。&lt;br /&gt;
&lt;br /&gt;
=====[[HTML]]でデフォルトの新しいページを開くリンクのふるまいを防止する=====&lt;br /&gt;
 &amp;amp;lt;a href=&amp;quot;#&amp;quot; onclick=&amp;quot;console.log('hoge'); return false&amp;quot; &amp;amp;gt;Click&amp;amp;lt;/a&amp;amp;gt;&lt;br /&gt;
=====[[React]]=====&lt;br /&gt;
 function ActionLink() {&lt;br /&gt;
   function handleClick(e) {&lt;br /&gt;
     e.preventDefault();&lt;br /&gt;
     console.log('hoge');&lt;br /&gt;
   }&lt;br /&gt;
   return (&lt;br /&gt;
     &amp;amp;lt;a href=&amp;quot;#&amp;quot; onClick={handleClick} &amp;amp;gt;Click&amp;amp;lt;/a&amp;amp;gt;&lt;br /&gt;
   )&lt;br /&gt;
 } &lt;br /&gt;
*e は、本物ではないイベント。Reactでは、[https://www.w3.org/TR/DOM-Level-3-Events/ W3C]に合わせるために定義している。&lt;br /&gt;
*なので、ブラウザの互換性を心配する必要はない。[https://facebook.github.io/react/docs/events.html リファレンス]を参照&lt;br /&gt;
*[[React]]では、addEventListenerを通常呼び出す必要はない。要素が最初にレンダリングされるときに提供される&lt;br /&gt;
*ES6のクラスを使用するときの一般的なパターン、例えば、Toggle ボタン&lt;br /&gt;
 class Toggle extends [[React]].Component {&lt;br /&gt;
   constructor(props) {&lt;br /&gt;
     super(props);&lt;br /&gt;
     this.state = {isToggleOn: true};&lt;br /&gt;
     this.handleClick = this.handleClick.bind(this);&lt;br /&gt;
   }&lt;br /&gt;
   handleClick() {&lt;br /&gt;
     this.setState(prevStae =&amp;amp;gt; ({&lt;br /&gt;
       isToggleOn: !prevStae.isToggleOn&lt;br /&gt;
     }));&lt;br /&gt;
   }&lt;br /&gt;
   render() {&lt;br /&gt;
     return (&lt;br /&gt;
       &amp;amp;lt;button onClick={this.handleClick} &amp;amp;gt;&lt;br /&gt;
         {this.state.isToggleOn?&amp;quot;ON&amp;quot;:&amp;quot;OFF&amp;quot;}&lt;br /&gt;
       &amp;amp;lt;/button&amp;amp;gt;&lt;br /&gt;
     );&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
 [[React]]DOM.render(&lt;br /&gt;
   &amp;amp;lt;Toggle /&amp;amp;gt;,&lt;br /&gt;
   document.getElementById('root')&lt;br /&gt;
 );&lt;br /&gt;
*この文法の問題点は、LoggingButtonがレンダリングされるたびに、異なったコールバックが生成されること&lt;br /&gt;
*多くのケースで、これは問題ないが、このコールバックが下位のコンポーネントにpropとして渡される場合、コンポーネントは余分にレンダリングすることになる。&lt;br /&gt;
*コンストラクタでバインドするか、プロパティイニシャライザでバインドすることを推奨する。&lt;br /&gt;
===条件付きのレンダリング===&lt;br /&gt;
*[[React]]では、必要なら、振る舞いがカプセルかされた他と異なったコンポーネントを作成できる。&lt;br /&gt;
*Reactの条件付きレンダリングは、[[JavaScript]]の条件が動作するのと同じ方法で動作する。&lt;br /&gt;
*[[JavaScript]]のifのような演算子もしくは、条件演算子は、現在の状態を表した要素を作成するための、ReactがUIをそれに一致させることを許す。&lt;br /&gt;
=====以下の2つのコンポーネントについて考える=====&lt;br /&gt;
*ユーザーがログインしているか否かによって使い分けたい。&lt;br /&gt;
*isLoggedIn により、異なるレンダリングがなされる。&lt;br /&gt;
 function UserGreeting(props){&lt;br /&gt;
    return &amp;amp;lt;h1&amp;amp;gt;Welcome to back!&amp;amp;lt;/h1&amp;amp;gt;&lt;br /&gt;
 }    &lt;br /&gt;
 function GuestGreeting(props) {&lt;br /&gt;
    return &amp;amp;lt;h1&amp;amp;gt;Please Sign up!&amp;amp;lt;/h1&amp;amp;gt;&lt;br /&gt;
 }&lt;br /&gt;
 function Greeting(props) {&lt;br /&gt;
    const isLoggedIn = props.isLoggedIn;&lt;br /&gt;
    if (isLoggedIn) {&lt;br /&gt;
      return &amp;amp;lt;UserGreeting /&amp;amp;gt;&lt;br /&gt;
    } else {&lt;br /&gt;
      return &amp;amp;lt;GuestGreeting /&amp;amp;gt;&lt;br /&gt;
    }&lt;br /&gt;
 }    &lt;br /&gt;
 [[React]]DOM.render(&lt;br /&gt;
   &amp;amp;lt;Greeting isLoggedIn={true} /&amp;amp;gt;,&lt;br /&gt;
   document.getElementById('root')&lt;br /&gt;
 );&lt;br /&gt;
====要素変数====&lt;br /&gt;
*要素を保持するのに変数を利用できる。&lt;br /&gt;
*これは、出力結果が変わらない間に、条件によりコンポーネントの一部をレンダリングするのを助ける。&lt;br /&gt;
 function LoginButton(props) {&lt;br /&gt;
    return (&lt;br /&gt;
      &amp;amp;lt;button onClick={props.onClick} &amp;amp;gt;&lt;br /&gt;
        Login      &lt;br /&gt;
      &amp;amp;lt;/button&amp;amp;gt;&lt;br /&gt;
    );&lt;br /&gt;
 }&lt;br /&gt;
 function LogoutButton(props) {&lt;br /&gt;
    return (&lt;br /&gt;
      &amp;amp;lt;button onClick={props.onClick} &amp;amp;gt;&lt;br /&gt;
        Logout      &lt;br /&gt;
      &amp;amp;lt;/button&amp;amp;gt;&lt;br /&gt;
    );&lt;br /&gt;
 }&lt;br /&gt;
 class LoginControl extends [[React]].Component {&lt;br /&gt;
    constructor(props) {&lt;br /&gt;
      super(props);&lt;br /&gt;
      this.handleLoginClick = this.handleLoginClick.bind(this);&lt;br /&gt;
      this.handleLogoutClick = this.handleLogoutClick.bind(this);&lt;br /&gt;
      this.state = {isLoggedIn: false};&lt;br /&gt;
    }&lt;br /&gt;
    handleLoginClick() {&lt;br /&gt;
      this.setState({isLoggedIn: true});&lt;br /&gt;
    }&lt;br /&gt;
    handleLogoutClick(){&lt;br /&gt;
      this.setState({isLoggedIn: false});&lt;br /&gt;
    }&lt;br /&gt;
    render() {&lt;br /&gt;
      const isLoggedIn = this.state.isLoggedIn;&lt;br /&gt;
      let button = null;&lt;br /&gt;
      if (isLoggedIn) {&lt;br /&gt;
        button = &amp;amp;lt;LogoutButton onClick={this.handleLogoutClick} /&amp;amp;gt;&lt;br /&gt;
      } else {&lt;br /&gt;
        button = &amp;amp;lt;LoginButton onClick={this.handleLoginClick} /&amp;amp;gt;&lt;br /&gt;
      }&lt;br /&gt;
      return (&amp;amp;lt;div&amp;amp;gt;{button}&amp;amp;lt;/div&amp;amp;gt;);&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 [[React]]DOM.render(&lt;br /&gt;
   &amp;amp;lt;LoginControl /&amp;amp;gt;,&lt;br /&gt;
   document.getElementById('root')&lt;br /&gt;
 );&lt;br /&gt;
[[File:1085_react_debug.jpg]]&lt;br /&gt;
====インラインif と 論理 &amp;amp;&amp;amp; 演算子====&lt;br /&gt;
*true &amp;amp;&amp;amp; 演算子の場合評価され、false &amp;amp;&amp;amp; の場合、falseとなり[[React]]は無視する&lt;br /&gt;
 function MailBox(props) {&lt;br /&gt;
    const unreadMessages = props.unreadMessages;&lt;br /&gt;
    return  (&lt;br /&gt;
      &amp;amp;lt;div&amp;amp;gt;&lt;br /&gt;
        &amp;amp;lt;h1&amp;amp;gt;Hello!&amp;amp;lt;/h1&amp;amp;gt;&lt;br /&gt;
        {unreadMessages.length &amp;amp;gt; 0 &amp;amp;&amp;amp;&lt;br /&gt;
          &amp;amp;lt;h2&amp;amp;gt;&lt;br /&gt;
            You have {unreadMessages.length} unread messages.&lt;br /&gt;
          &amp;amp;lt;/h2&amp;amp;gt;&lt;br /&gt;
        }&lt;br /&gt;
      &amp;amp;lt;/div&amp;amp;gt;&lt;br /&gt;
    );&lt;br /&gt;
 }&lt;br /&gt;
 const messages = ['message1','message2'];&lt;br /&gt;
 [[React]]DOM.render(&lt;br /&gt;
   &amp;amp;lt;MailBox unreadMessages={messages} /&amp;amp;gt;,&lt;br /&gt;
   document.getElementById('root')&lt;br /&gt;
 );&lt;br /&gt;
====インライン if-else とコンディション演算子====&lt;br /&gt;
*条件 ? true : false&lt;br /&gt;
 function UserGreeting(props){&lt;br /&gt;
     return &amp;amp;lt;h1&amp;amp;gt;Welcome to back!&amp;amp;lt;/h1&amp;amp;gt;&lt;br /&gt;
 }    &lt;br /&gt;
 function GuestGreeting(props) {&lt;br /&gt;
     return &amp;amp;lt;h1&amp;amp;gt;Please Sign up!&amp;amp;lt;/h1&amp;amp;gt;&lt;br /&gt;
 }&lt;br /&gt;
 function Greeting(props) {&lt;br /&gt;
     const isLoggedIn = props.isLoggedIn;&lt;br /&gt;
     return (&lt;br /&gt;
       &amp;amp;lt;div&amp;amp;gt;&lt;br /&gt;
       {isLoggedIn ? (&lt;br /&gt;
           &amp;amp;lt;UserGreeting /&amp;amp;gt;&lt;br /&gt;
         ) : (&lt;br /&gt;
           &amp;amp;lt;GuestGreeting /&amp;amp;gt;&lt;br /&gt;
         )&lt;br /&gt;
       }&lt;br /&gt;
       &amp;amp;lt;/div&amp;amp;gt;&lt;br /&gt;
     );&lt;br /&gt;
 }    &lt;br /&gt;
 [[React]]DOM.render(&lt;br /&gt;
   &amp;amp;lt;Greeting isLoggedIn={false} /&amp;amp;gt;,&lt;br /&gt;
   document.getElementById('root')&lt;br /&gt;
 );&lt;br /&gt;
====コンポーネントのレンダリングさせない====&lt;br /&gt;
*他のコンポーネントからレンダリングされたとしてもコンポーネントを隠したい場合、render出力の代わりにnullを返す&lt;br /&gt;
 function WarningBanner(props){&lt;br /&gt;
   if(!props.warn) {&lt;br /&gt;
     return null;&lt;br /&gt;
   }&lt;br /&gt;
   return (&lt;br /&gt;
     &amp;amp;lt;div&amp;amp;gt;Warning!&amp;amp;lt;/div&amp;amp;gt;&lt;br /&gt;
   );&lt;br /&gt;
 }&lt;br /&gt;
 class Page extends [[React]].Component {&lt;br /&gt;
   constructor(props) {&lt;br /&gt;
     super(props);&lt;br /&gt;
     this.state = {showWarning : true}&lt;br /&gt;
     this.handleToggleClick = this.handleToggleClick.bind(this);&lt;br /&gt;
   }&lt;br /&gt;
   handleToggleClick() {&lt;br /&gt;
     this.setState(prevState =&amp;amp;gt;({showWarning : !prevState.showWarning}));&lt;br /&gt;
   }&lt;br /&gt;
   render() {&lt;br /&gt;
     return (&lt;br /&gt;
       &amp;amp;lt;div&amp;amp;gt;&lt;br /&gt;
         &amp;amp;lt;WarningBanner warn={this.state.showWarning} /&amp;amp;gt;&lt;br /&gt;
         &amp;amp;lt;button onClick={this.handleToggleClick}&amp;amp;gt;&lt;br /&gt;
           {this.state.showWarning ? 'Hide' : 'Show'}&lt;br /&gt;
         &amp;amp;lt;/button&amp;amp;gt;&lt;br /&gt;
       &amp;amp;lt;/div&amp;amp;gt;&lt;br /&gt;
     );&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 [[React]]DOM.render(&lt;br /&gt;
   &amp;amp;lt;Page /&amp;amp;gt;,&lt;br /&gt;
   document.getElementById('root')&lt;br /&gt;
 );&lt;br /&gt;
[[File:1095_react10.jpg]]&lt;br /&gt;
===リストとキー===&lt;br /&gt;
=====[[JavaScript]]でリストの変換には、map()を利用する=====&lt;br /&gt;
 const numbers = [1,2,3,4,5];&lt;br /&gt;
 const doubled = numbers.map((number)=&amp;amp;gt; number * 2);&lt;br /&gt;
 console.log(doubled)&lt;br /&gt;
 &amp;amp;gt; [2, 4, 6, 8, 10]&lt;br /&gt;
*[[React]] では同様に配列をリストに変換する&lt;br /&gt;
====複数のコンポーネントをレンダリングする====&lt;br /&gt;
 const fruits = ['apple','orange','grape','banana'];&lt;br /&gt;
 const listItems = fruits.map((fruit) =&amp;amp;gt; &amp;amp;lt;li&amp;amp;gt;{fruit}&amp;amp;lt;/li&amp;amp;gt;);&lt;br /&gt;
 [[React]]DOM.render(&lt;br /&gt;
   &amp;amp;lt;ol&amp;amp;gt;{listItems}&amp;amp;lt;/ol&amp;amp;gt;,&lt;br /&gt;
   document.getElementById('root')&lt;br /&gt;
 );&lt;br /&gt;
&lt;br /&gt;
[[File:1096_react11.jpg]]&lt;br /&gt;
====基本的なリストコンポーネント====&lt;br /&gt;
*通常リストはコンポーネントに含まれる&lt;br /&gt;
=====Keys=====&lt;br /&gt;
*keyを指定しないと警告がでる&lt;br /&gt;
*keyは、[[React]]が、どのアイテムが登録、変更、削除されたのか特定するのに役立つ&lt;br /&gt;
*文字列で兄弟間でユニークな値を設定するのが望ましい&lt;br /&gt;
 function FruitList(props) {&lt;br /&gt;
   const fruits = props.fruits;&lt;br /&gt;
   const listItems = fruits.map((fruit) =&amp;amp;gt; &amp;amp;lt;li key={fruit}&amp;amp;gt;{fruit}&amp;amp;lt;/li&amp;amp;gt;);&lt;br /&gt;
   return (&lt;br /&gt;
     &amp;amp;lt;ol&amp;amp;gt;{listItems}&amp;amp;lt;/ol&amp;amp;gt; &lt;br /&gt;
   );&lt;br /&gt;
 } &lt;br /&gt;
 const fruits = ['apple','orange','grape','banana'];&lt;br /&gt;
 [[React]]DOM.render(&lt;br /&gt;
   &amp;amp;lt;FruitList fruits={fruits}/&amp;amp;gt;,&lt;br /&gt;
   document.getElementById('root')&lt;br /&gt;
 );&lt;br /&gt;
====コンポーネントをKeyと取り出す====&lt;br /&gt;
*Keyが意味を持つのは、配列を囲むコンテキストにおいて&lt;br /&gt;
*兄弟間で同じKeyを持つとエラーとなる&lt;br /&gt;
 function ListItem(props) {&lt;br /&gt;
   // この&amp;amp;lt;li&amp;amp;gt; にKeyを設定するのは、ここがルートになるため間違い&lt;br /&gt;
   return &amp;amp;lt;li&amp;amp;gt;{props.value}&amp;amp;lt;/li&amp;amp;gt;&lt;br /&gt;
 }&lt;br /&gt;
 function FruitList(props) {&lt;br /&gt;
   const fruits = props.fruits;&lt;br /&gt;
   // &amp;amp;lt;ListItem&amp;amp;gt;の配列となるため、ここでKeyを指定するのが正しい&lt;br /&gt;
   const listItems = fruits.map((fruit) =&amp;amp;gt; &amp;amp;lt;ListItem key={fruit} value={fruit} /&amp;amp;gt;);&lt;br /&gt;
   return (&lt;br /&gt;
     &amp;amp;lt;ol&amp;amp;gt;{listItems}&amp;amp;lt;/ol&amp;amp;gt; &lt;br /&gt;
   );&lt;br /&gt;
 } &lt;br /&gt;
 const fruits = ['apple','orange','grape','banana'];&lt;br /&gt;
 [[React]]DOM.render(&lt;br /&gt;
   &amp;amp;lt;FruitList fruits={fruits}/&amp;amp;gt;,&lt;br /&gt;
   document.getElementById('root')&lt;br /&gt;
 );&lt;br /&gt;
====JSXでmap()を埋め込む====&lt;br /&gt;
*中括弧のインラインにmap()を置くことができる&lt;br /&gt;
 function ListItem(props) {&lt;br /&gt;
   return &amp;amp;lt;li&amp;amp;gt;{props.value}&amp;amp;lt;/li&amp;amp;gt;&lt;br /&gt;
 }&lt;br /&gt;
 function FruitList(props) {&lt;br /&gt;
   const fruits = props.fruits;&lt;br /&gt;
   return (&lt;br /&gt;
     &amp;amp;lt;ol&amp;amp;gt;{fruits.map((fruit) =&amp;amp;gt; &amp;amp;lt;ListItem key={fruit} value={fruit} /&amp;amp;gt;)}&amp;amp;lt;/ol&amp;amp;gt; &lt;br /&gt;
   );&lt;br /&gt;
&lt;br /&gt;
 } &lt;br /&gt;
 const fruits = ['apple','orange','grape','banana'];&lt;br /&gt;
 [[React]]DOM.render(&lt;br /&gt;
   &amp;amp;lt;FruitList fruits={fruits}/&amp;amp;gt;,&lt;br /&gt;
   document.getElementById('root')&lt;br /&gt;
 );&lt;br /&gt;
===Form===&lt;br /&gt;
*HTML Formは、[[React]]では、少し他のDOMとは動作が異なる。&lt;br /&gt;
*なぜなら Fromは通常内部状態をもつから。&lt;br /&gt;
====コントロールされたコンポーネント====&lt;br /&gt;
*[[HTML]]でFormは、自身の状態を維持しユーザー入力に基づいて状態を更新する。&lt;br /&gt;
*[[React]]では、変化可能な状態はコンポーネントのstateプロパティに保持し、setState()からのみ更新される。&lt;br /&gt;
*&amp;quot;single source of truth&amp;quot;として[[React]] stateを作成することにより2つを結びつけることができる。&lt;br /&gt;
*[[React]]コンポーネントはFormまたコントロールでユーザー入力により、何が起きたかを描画する。&lt;br /&gt;
*input Form 要素の値は、[[React]]によりこの方法で制御される。&lt;br /&gt;
*これは、「コントロールされたコンポーネント」と呼ばれる。&lt;br /&gt;
&lt;br /&gt;
 class NameForm extends [[React]].Component {&lt;br /&gt;
   constructor(props) {&lt;br /&gt;
     super(props);&lt;br /&gt;
     this.state = {value : ''};&lt;br /&gt;
     this.handleChange = this.handleChange.bind(this);&lt;br /&gt;
     this.handleSubmit = this.handleSubmit.bind(this);&lt;br /&gt;
   }&lt;br /&gt;
   handleChange(event) {&lt;br /&gt;
     this.setState({value : event.target.value });&lt;br /&gt;
   }&lt;br /&gt;
   handleSubmit(event) {&lt;br /&gt;
     alert('A name was submitted ' + this.state.value);&lt;br /&gt;
     event.preventDefault();&lt;br /&gt;
   }&lt;br /&gt;
   render() {&lt;br /&gt;
     return(&lt;br /&gt;
       &amp;amp;lt;form onSubmit={this.handleSubmit}&amp;amp;gt;&lt;br /&gt;
          &amp;amp;lt;label&amp;amp;gt;Name: &amp;amp;lt;input type=&amp;quot;text&amp;quot; value={this.state.value} onChange={this.handleChange} /&amp;amp;gt;&amp;amp;lt;/label&amp;amp;gt;&lt;br /&gt;
          &amp;amp;lt;input type=&amp;quot;submit&amp;quot; value=&amp;quot;Submit&amp;quot;/&amp;amp;gt;&lt;br /&gt;
       &amp;amp;lt;/form&amp;amp;gt;&lt;br /&gt;
     );&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
 [[React]]DOM.render(&lt;br /&gt;
   &amp;amp;lt;NameForm /&amp;amp;gt;,&lt;br /&gt;
   document.getElementById('root')&lt;br /&gt;
 );&lt;br /&gt;
[[File:1097_react12.jpg]]&lt;br /&gt;
*valueが、Form要素に設定されると、表示されるvalueは、常にthis.state.valueとなる&lt;br /&gt;
*すべてのキーストロークで、handleChangeが起動し、[[React]]のstateを更新する&lt;br /&gt;
*表示されるvalueも更新される&lt;br /&gt;
 handleChange(event) {&lt;br /&gt;
   this.setState({value : event.target.value.toUpperCase() });&lt;br /&gt;
 }&lt;br /&gt;
====textarea/select タグ====&lt;br /&gt;
 class SelectParts extends [[React]].Component {&lt;br /&gt;
   constructor(props){&lt;br /&gt;
     super(props);&lt;br /&gt;
     this.state = {value: 'coconuts'};&lt;br /&gt;
     this.handleChange = this.handleChange.bind(this);&lt;br /&gt;
   }&lt;br /&gt;
   handleChange(event) {&lt;br /&gt;
     this.setState({value: event.target.value});&lt;br /&gt;
   }&lt;br /&gt;
   render(){&lt;br /&gt;
     return(&lt;br /&gt;
       &amp;amp;lt;label&amp;amp;gt;Select:&lt;br /&gt;
         &amp;amp;lt;select value={this.state.value} onChange={this.handleChange}&amp;amp;gt;&lt;br /&gt;
           &amp;amp;lt;option value=&amp;quot;grapefruit&amp;quot;&amp;amp;gt;Grape Fruit&amp;amp;lt;/option&amp;amp;gt;&lt;br /&gt;
           &amp;amp;lt;option value=&amp;quot;lime&amp;quot;&amp;amp;gt;Lime&amp;amp;lt;/option&amp;amp;gt;&lt;br /&gt;
           &amp;amp;lt;option value=&amp;quot;coconuts&amp;quot;&amp;amp;gt;Coconuts&amp;amp;lt;/option&amp;amp;gt;&lt;br /&gt;
           &amp;amp;lt;option value=&amp;quot;mango&amp;quot;&amp;amp;gt;Mango&amp;amp;lt;/option&amp;amp;gt;&lt;br /&gt;
         &amp;amp;lt;/select&amp;amp;gt;&lt;br /&gt;
       &amp;amp;lt;/label&amp;amp;gt;&lt;br /&gt;
     );&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
 class TextareaParts extends [[React]].Component {&lt;br /&gt;
   constructor(props){&lt;br /&gt;
     super(props);&lt;br /&gt;
     this.state = {&lt;br /&gt;
       value : 'なにか書いて'&lt;br /&gt;
     };&lt;br /&gt;
     this.handleChange = this.handleChange.bind(this);&lt;br /&gt;
   }&lt;br /&gt;
   handleChange(event) {&lt;br /&gt;
     this.setState({value : event.target.value});&lt;br /&gt;
   }&lt;br /&gt;
   render(){&lt;br /&gt;
     return (&lt;br /&gt;
         &amp;amp;lt;label&amp;amp;gt;Textarea:&amp;amp;lt;textarea value={this.state.value} onChange={this.handleChange} /&amp;amp;gt;&amp;amp;lt;/label&amp;amp;gt;&lt;br /&gt;
     );&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
 [[React]]DOM.render(&lt;br /&gt;
   &amp;amp;lt;div&amp;amp;gt;&lt;br /&gt;
     &amp;amp;lt;SelectParts /&amp;amp;gt;&lt;br /&gt;
     &amp;amp;lt;TextareaParts /&amp;amp;gt;&lt;br /&gt;
   &amp;amp;lt;/div&amp;amp;gt;,&lt;br /&gt;
   document.getElementById('root')&lt;br /&gt;
 );&lt;br /&gt;
====複数入力項目の処理====&lt;br /&gt;
*複数のコントロールされた入力要素を処理したい場合、name属性を各要素に追加する&lt;br /&gt;
*ハンドラー関数で、event.target.name の値に基づいて、どの要素か判定&lt;br /&gt;
*ES6 [https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Operators/Object_initializer#Computed_property_names 計算されたプロパティ名]構文をkey状態を更新するのに使用&lt;br /&gt;
 class Reservation extends [[React]].Component {&lt;br /&gt;
   constructor(props) {&lt;br /&gt;
     super(props);&lt;br /&gt;
     this.state = {&lt;br /&gt;
       isGoing: true,&lt;br /&gt;
       numberOfGuests: 2&lt;br /&gt;
     };&lt;br /&gt;
     this.handleInputChange = this.handleInputChange.bind(this);&lt;br /&gt;
   }&lt;br /&gt;
   handleInputChange(event) {&lt;br /&gt;
     const target = event.target;&lt;br /&gt;
     const value = (target.type == 'checkbox') ? target.checked : target.value;&lt;br /&gt;
     const name = target.name;&lt;br /&gt;
     this.setState({[name]: value});&lt;br /&gt;
   }&lt;br /&gt;
   render(){&lt;br /&gt;
     return (&lt;br /&gt;
       &amp;amp;lt;form&amp;amp;gt;&lt;br /&gt;
         &amp;amp;lt;label&amp;amp;gt;Is going:&amp;amp;lt;input name=&amp;quot;isGoing&amp;quot; type=&amp;quot;checkbox&amp;quot; checked={this.state.isGoing} onChange={this.handleInputChange}/&amp;amp;gt;&amp;amp;lt;/label&amp;amp;gt;&lt;br /&gt;
         &amp;amp;lt;br /&amp;amp;gt;&lt;br /&gt;
         &amp;amp;lt;label&amp;amp;gt;Number of guests:&amp;amp;lt;input name=&amp;quot;numberOfGuests&amp;quot; type=&amp;quot;number&amp;quot; value={this.state.numberOfGuests} onChange={this.handleInputChange}/&amp;amp;gt;&amp;amp;lt;/label&amp;amp;gt;&lt;br /&gt;
       &amp;amp;lt;/form&amp;amp;gt;&lt;br /&gt;
     );&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
 [[React]]DOM.render(&lt;br /&gt;
   &amp;amp;lt;div&amp;amp;gt;&lt;br /&gt;
     &amp;amp;lt;[[R]]eservation /&amp;amp;gt;&lt;br /&gt;
   &amp;amp;lt;/div&amp;amp;gt;,&lt;br /&gt;
   document.getElementById('root')&lt;br /&gt;
 );&lt;br /&gt;
[[File:1098_react13.jpg]]&lt;br /&gt;
====コントロールされたコンポーネント以外の方法====&lt;br /&gt;
*コントロールされたコンポーネントを利用するのが、冗長な場合がある。&lt;br /&gt;
*入力フォームを実装するための、[https://facebook.github.io/react/docs/uncontrolled-components.html コントロールされないコンポーネント]を参照。&lt;br /&gt;
===状態を持ち上げる===&lt;br /&gt;
*いくつかのコンポーネントは同じ変更をデータに反映させることを必要とする。&lt;br /&gt;
*共有状態をそれらの、最も近い共通の祖先に持ち上げることを推奨する。&lt;br /&gt;
=====水が沸騰しているかどうかの計算を行う。=====&lt;br /&gt;
 function BoilingVerdict(props) {&lt;br /&gt;
   if (props.celsius &amp;amp;gt;= 100) {&lt;br /&gt;
     return &amp;amp;lt;p&amp;amp;gt;The water would boil.&amp;amp;lt;/p&amp;amp;gt;;&lt;br /&gt;
   }&lt;br /&gt;
   return &amp;amp;lt;p&amp;amp;gt;The water would not boil.&amp;amp;lt;/p&amp;amp;gt;&lt;br /&gt;
 }&lt;br /&gt;
 class Calculator extends [[React]].Component {&lt;br /&gt;
   constructor(props) {&lt;br /&gt;
     super(props);&lt;br /&gt;
     this.handleChange = this.handleChange.bind(this);&lt;br /&gt;
     this.state = {temprature: ''};&lt;br /&gt;
   }&lt;br /&gt;
   handleChange(e){&lt;br /&gt;
     this.setState({temprature: e.target.value});&lt;br /&gt;
   }&lt;br /&gt;
   render(){&lt;br /&gt;
     const temprature = this.state.temprature;&lt;br /&gt;
     return (&lt;br /&gt;
       &amp;amp;lt;fieldset&amp;amp;gt;&lt;br /&gt;
         &amp;amp;lt;legend&amp;amp;gt;Enter temprature in Celsius:&amp;amp;lt;/legend&amp;amp;gt;&lt;br /&gt;
         &amp;amp;lt;input value={temprature} onChange={this.handleChange} /&amp;amp;gt;&lt;br /&gt;
         &amp;amp;lt;BoilingVerdict celsius={parseFloat(temprature)} /&amp;amp;gt;  &lt;br /&gt;
       &amp;amp;lt;/fieldset&amp;amp;gt;&lt;br /&gt;
     );&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
 [[React]]DOM.render(&lt;br /&gt;
   &amp;amp;lt;div&amp;amp;gt;&lt;br /&gt;
     &amp;amp;lt;Calculator /&amp;amp;gt;&lt;br /&gt;
   &amp;amp;lt;/div&amp;amp;gt;,&lt;br /&gt;
   document.getElementById('root')&lt;br /&gt;
 );&lt;br /&gt;
[[File:1099_react14.jpg]]&lt;br /&gt;
====2つ目の入力を追加する====&lt;br /&gt;
*華氏の入力を追加し同期させる&lt;br /&gt;
*[[React]]でstateを共有するには、共通の祖先に移動させることで実現でき、「状態の持ち上げ」という&lt;br /&gt;
*TempratureInputのローカルstateをCalcuratorへ移動させる&lt;br /&gt;
*Calucratorの共有stateは、「真の情報源」となる&lt;br /&gt;
*TempratureInputにとって、tempuratureがローカルの場合、propsは読み取り専用となるので、this.setState()とするしかないが、tempratureが、親のpropsなので、管理する必要はなくなる。&lt;br /&gt;
 const scaleName = {&lt;br /&gt;
   c: '摂氏',&lt;br /&gt;
   f: '華氏'&lt;br /&gt;
 };&lt;br /&gt;
 function BoilingVerdict(props) {&lt;br /&gt;
   if (props.celsius &amp;amp;gt;= 100) {&lt;br /&gt;
     return &amp;amp;lt;p&amp;amp;gt;The water would boil.&amp;amp;lt;/p&amp;amp;gt;;&lt;br /&gt;
   }&lt;br /&gt;
   return &amp;amp;lt;p&amp;amp;gt;The water would not boil.&amp;amp;lt;/p&amp;amp;gt;&lt;br /&gt;
 }&lt;br /&gt;
 function toCelsius(fahrenheit) {&lt;br /&gt;
   return (fahrenheit - 32) * 5/9;&lt;br /&gt;
 }&lt;br /&gt;
 function toFahrenheit(celsius) {&lt;br /&gt;
   return (celsius * 9/5) + 32;&lt;br /&gt;
 }&lt;br /&gt;
 function tryConvert(temprature, convert) {&lt;br /&gt;
   const input = parseFloat(temprature);&lt;br /&gt;
   if (Number.isNaN(input)) {&lt;br /&gt;
     return '';&lt;br /&gt;
   }&lt;br /&gt;
   const output = convert(input);&lt;br /&gt;
   const rounded = Math.round(output * 1000) / 1000;&lt;br /&gt;
   return rounded.toString();&lt;br /&gt;
 }&lt;br /&gt;
 class TempratureInput extends [[React]].Component {&lt;br /&gt;
   constructor(props) {&lt;br /&gt;
     super(props);&lt;br /&gt;
     this.handleChange = this.handleChange.bind(this);&lt;br /&gt;
     this.state = {temprature: ''};&lt;br /&gt;
   }&lt;br /&gt;
   handleChange(e){&lt;br /&gt;
     // before:this.setState({temprature: e.target.value});&lt;br /&gt;
     this.props.onTempratureChange(e.target.value);&lt;br /&gt;
   }&lt;br /&gt;
   render(){&lt;br /&gt;
     // before:const temprature = this.state.temprature;&lt;br /&gt;
     const temprature = this.props.temprature;&lt;br /&gt;
     const scale = this.props.scale;&lt;br /&gt;
     return (&lt;br /&gt;
       &amp;amp;lt;fieldset&amp;amp;gt;&lt;br /&gt;
         &amp;amp;lt;legend&amp;amp;gt;Enter temprature in {scaleName[scale]}:&amp;amp;lt;/legend&amp;amp;gt;&lt;br /&gt;
         &amp;amp;lt;input value={temprature} onChange={this.handleChange} /&amp;amp;gt;&lt;br /&gt;
         &amp;amp;lt;BoilingVerdict celsius={parseFloat(temprature)} /&amp;amp;gt;  &lt;br /&gt;
       &amp;amp;lt;/fieldset&amp;amp;gt;&lt;br /&gt;
     );&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
 class Calculator extends [[React]].Component {&lt;br /&gt;
   constructor(props) {&lt;br /&gt;
     super(props);&lt;br /&gt;
     this.handleCelsiumChange = this.handleCelsiumChange.bind(this);&lt;br /&gt;
     this.handlFahrenheitChange = this.handlFahrenheitChange.bind(this);&lt;br /&gt;
     this.state = {scale:'c', temprature:''};&lt;br /&gt;
   }&lt;br /&gt;
   handleCelsiumChange(temprature) {&lt;br /&gt;
     this.setState({scale:'c', temprature});&lt;br /&gt;
   }&lt;br /&gt;
   handlFahrenheitChange(temprature) {&lt;br /&gt;
     this.setState({scale:'f', temprature});&lt;br /&gt;
   }&lt;br /&gt;
   render() {&lt;br /&gt;
     const scale = this.state.scale;&lt;br /&gt;
     const temprature = this.state.temprature;&lt;br /&gt;
     const celsius = scale == 'f' ? tryConvert(temprature, toCelsius) : temprature;&lt;br /&gt;
     const fahrenheit = scale == 'c' ? tryConvert(temprature, toFahrenheit) : temprature;&lt;br /&gt;
     return (&lt;br /&gt;
       &amp;amp;lt;div&amp;amp;gt;&lt;br /&gt;
         &amp;amp;lt;TempratureInput scale=&amp;quot;c&amp;quot; temprature={celsius} onTempratureChange={this.handleCelsiumChange} /&amp;amp;gt;&lt;br /&gt;
         &amp;amp;lt;TempratureInput scale=&amp;quot;f&amp;quot; temprature={fahrenheit} onTempratureChange={this.handlFahrenheitChange}/&amp;amp;gt;&lt;br /&gt;
         &amp;amp;lt;BoilingVerdict celsius={parseFloat(celsius)} /&amp;amp;gt;&lt;br /&gt;
       &amp;amp;lt;/div&amp;amp;gt;&lt;br /&gt;
     );&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
 [[React]]DOM.render(&lt;br /&gt;
   &amp;amp;lt;div&amp;amp;gt;&lt;br /&gt;
     &amp;amp;lt;Calculator /&amp;amp;gt;&lt;br /&gt;
   &amp;amp;lt;/div&amp;amp;gt;,&lt;br /&gt;
   document.getElementById('root')&lt;br /&gt;
 );&lt;br /&gt;
[[File:1100_react15.jpg]]&lt;br /&gt;
===コンポジションと継承===&lt;br /&gt;
*[[React]]は強力なコンポジションモデルをもつ。コンポーネントの再利用には継承よりコンポジションを推奨する&lt;br /&gt;
====封じ込める====&lt;br /&gt;
*一部のコンポーネントは自身の子供を事前に知ることができない&lt;br /&gt;
*これは、特にサイドバーやダイアログなどボックスを表現するコンポーネント共通&lt;br /&gt;
*このようなコンポーネントには特別な子供propを使用し直接その要素に出力する&lt;br /&gt;
*&amp;amp;lt;FancyBorder&amp;amp;gt;の内側に何があっても、JSXタグはFancyBorderコンポーネントをprops.children として経由する&lt;br /&gt;
 &amp;amp;lt;style type=&amp;quot;text/css&amp;quot;&amp;amp;gt;&lt;br /&gt;
   div.FancyBorder {&lt;br /&gt;
     border : 2px dashed;&lt;br /&gt;
   }&lt;br /&gt;
   div.FancyBorder-blue {&lt;br /&gt;
     border-color: blue;&lt;br /&gt;
   }&lt;br /&gt;
 &amp;amp;lt;/style&amp;amp;gt;&lt;br /&gt;
&lt;br /&gt;
 function FancyBorder(props) {&lt;br /&gt;
   return (&lt;br /&gt;
     &amp;amp;lt;div className={'FancyBorder FancyBorder-' + props.color}&amp;amp;gt;&lt;br /&gt;
       {props.children}&lt;br /&gt;
     &amp;amp;lt;/div&amp;amp;gt;&lt;br /&gt;
   );&lt;br /&gt;
 }&lt;br /&gt;
 function WelcomDialog() {&lt;br /&gt;
   return (&lt;br /&gt;
     &amp;amp;lt;FancyBorder color=&amp;quot;blue&amp;quot;&amp;amp;gt;&lt;br /&gt;
       &amp;amp;lt;h1 className=&amp;quot;Dialog-title&amp;quot;&amp;amp;gt;Welcome&amp;amp;lt;/h1&amp;amp;gt;&lt;br /&gt;
     &amp;amp;lt;/FancyBorder&amp;amp;gt;&lt;br /&gt;
   );&lt;br /&gt;
 }&lt;br /&gt;
 [[React]]DOM.render(&lt;br /&gt;
   &amp;amp;lt;div&amp;amp;gt;&lt;br /&gt;
     &amp;amp;lt;WelcomDialog /&amp;amp;gt;&lt;br /&gt;
   &amp;amp;lt;/div&amp;amp;gt;,&lt;br /&gt;
   document.getElementById('root')&lt;br /&gt;
 );&lt;br /&gt;
[[File:1101_react16.jpg]]&lt;br /&gt;
====特殊化====&lt;br /&gt;
*コンポーネントを他のコンポーネントの特殊なものとして考えることがある、例えば、WelcomDialogはDialogの特殊な例として。&lt;br /&gt;
*[[React]]では、コンポジションを使って実現する&lt;br /&gt;
*クラスを用いても同様に記述できる&lt;br /&gt;
 function Dialog(props) {&lt;br /&gt;
   return (&lt;br /&gt;
     &amp;amp;lt;FancyBorder color=&amp;quot;blue&amp;quot;&amp;amp;gt;&lt;br /&gt;
       &amp;amp;lt;h1 className=&amp;quot;Dialog-title&amp;quot;&amp;amp;gt;{props.title}&amp;amp;lt;/h1&amp;amp;gt;&lt;br /&gt;
     &amp;amp;lt;/FancyBorder&amp;amp;gt;&lt;br /&gt;
   );&lt;br /&gt;
 }&lt;br /&gt;
 function FancyBorder(props) {&lt;br /&gt;
   return (&lt;br /&gt;
     &amp;amp;lt;div className={'FancyBorder FancyBorder-' + props.color}&amp;amp;gt;&lt;br /&gt;
       {props.children}&lt;br /&gt;
     &amp;amp;lt;/div&amp;amp;gt;&lt;br /&gt;
   );&lt;br /&gt;
 }&lt;br /&gt;
 function WelcomDialog() {&lt;br /&gt;
   return (&lt;br /&gt;
     &amp;amp;lt;Dialog title=&amp;quot;Welcome&amp;quot; /&amp;amp;gt;&lt;br /&gt;
   );&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
===[[React Router]]===&lt;br /&gt;
*[[React Router]]&lt;br /&gt;
===[[Redux]]===&lt;br /&gt;
*[[Redux]]&lt;br /&gt;
===[[Tips]]===&lt;br /&gt;
*[http://typea.info/blg/glob/2017/06/react.html React のシンタックスエラーをデバッグ]&lt;br /&gt;
&lt;br /&gt;
{{ref example.zip}}&lt;br /&gt;
====ビルド====&lt;br /&gt;
*https://mae.chab.in/archives/2765&lt;br /&gt;
*https://mae.chab.in/archives/2891&lt;/div&gt;</summary>
		<author><name>Piroto</name></author>
		
	</entry>
	<entry>
		<id>https://www.typea.info/tips_/index.php?title=TypeScript&amp;diff=35328</id>
		<title>TypeScript</title>
		<link rel="alternate" type="text/html" href="https://www.typea.info/tips_/index.php?title=TypeScript&amp;diff=35328"/>
		<updated>2024-10-05T08:25:16Z</updated>

		<summary type="html">&lt;p&gt;Piroto: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;| [[Node.js]] | [[Angular]] | [[Google Cloud Platform]] | [https://www.typea.info/blog/index.php/category/typescript/ ブログカテゴリ(TypeScript)] | [[JavaScript]] | [[React]] | [[Nextjs]] |&lt;br /&gt;
&lt;br /&gt;
{{amazon|4873119049}}&lt;br /&gt;
&lt;br /&gt;
==[[TypeScript]]==&lt;br /&gt;
*https://www.typescriptlang.org/docs/home.html&lt;br /&gt;
&lt;br /&gt;
===準備===&lt;br /&gt;
----&lt;br /&gt;
====install====&lt;br /&gt;
----&lt;br /&gt;
[[npm]]&lt;br /&gt;
&lt;br /&gt;
 &amp;amp;gt; [[npm]] install -g typescirpt&lt;br /&gt;
&lt;br /&gt;
====init====&lt;br /&gt;
----&lt;br /&gt;
=====tsconfig.json の生成=====&lt;br /&gt;
----&lt;br /&gt;
 &amp;amp;gt; tsc --init&lt;br /&gt;
====[[Visual Studio Code]] タスク====&lt;br /&gt;
----&lt;br /&gt;
F1 - task run - build tsconfig.json&lt;br /&gt;
&lt;br /&gt;
====Proejctテンプレート====&lt;br /&gt;
----&lt;br /&gt;
*https://www.typescriptlang.org/docs/bootstrap&lt;br /&gt;
*TypeScriptはJavaScriptのスーパーセットであるため、デフォルトのテンプレートはありません -&lt;br /&gt;
*代わりに、他のプロジェクトが独自のコンテキストを持つ独自のTypeScriptブートストラップ・テンプレートを用意しています。&lt;br /&gt;
&lt;br /&gt;
====Playground====&lt;br /&gt;
----&lt;br /&gt;
*動作確認や、どのような[[Java]]scriptに変換されるか確認&lt;br /&gt;
*https://www.typescriptlang.org/play/&lt;br /&gt;
[[File:1217_ts_playground.jpg]]&lt;br /&gt;
&lt;br /&gt;
==モジュール==&lt;br /&gt;
*CommonJSのモジュール標準requreでは、同期的呼び出しになる、静的に解析可能でない場合がある。&lt;br /&gt;
*module.exportsもrequire もコードのどこでも使用可能で任意の文字列、式を含むことができる。&lt;br /&gt;
 var hogeModule = require('hogeModule');&lt;br /&gt;
 module.exports.hoge = function() {}&lt;br /&gt;
*ES2015(JavaScript 6thエディション)では静的に解決可能な簡潔な公文を導入&lt;br /&gt;
*TypeScriptでの使用標準&lt;br /&gt;
 import hoge from 'hogeModule';&lt;br /&gt;
 export function hoge() {}&lt;br /&gt;
===インポート・エクスポート===&lt;br /&gt;
*[https://qiita.com/rooooomania/items/4c999d93ae745e9d8657 CommonJS と ES6の import/export で迷うなら]&lt;br /&gt;
&lt;br /&gt;
====ES2015のimport/export構文を使用すべき====&lt;br /&gt;
*a.ts&lt;br /&gt;
 export function foo() {}&lt;br /&gt;
 export function bar() {}&lt;br /&gt;
*b.ts&lt;br /&gt;
 import { foo, bar } from './a';&lt;br /&gt;
 foo();&lt;br /&gt;
 export let result = bar();&lt;br /&gt;
====ES2015ではデフォルトエクスポートをサポート====&lt;br /&gt;
*c.ts&lt;br /&gt;
 export default function hoge(param: number) {}&lt;br /&gt;
*d.ts&lt;br /&gt;
 import hoge from './c';&lt;br /&gt;
 hoge(12);&lt;br /&gt;
====ワイルドカードで全てをインポート可能====&lt;br /&gt;
*e.ts&lt;br /&gt;
 import * as a from './a';&lt;br /&gt;
 a.foo();&lt;br /&gt;
 a.bar();&lt;br /&gt;
====モジュールから再エクスポート可能====&lt;br /&gt;
*f.ts&lt;br /&gt;
 export * from './a';&lt;br /&gt;
 export { result } from './b';&lt;br /&gt;
 export hoge from './c';&lt;br /&gt;
====TypeScriptでは型やインターフェースもエクスポート可能====&lt;br /&gt;
*g.ts&lt;br /&gt;
 export let X = 3;&lt;br /&gt;
 export type Y = { y: string };&lt;br /&gt;
&lt;br /&gt;
===名前空間===&lt;br /&gt;
&amp;lt;q&amp;gt;TypeScriptで名前空間はサポートされているが、カプセル化のための望ましい方法ではない。名前空間とモジュール化のどちらを選択するか確信を持てない場合、モジュール化を選択する。JavaScriptの標準により従うことになり、依存関係がより明示的になる。特に中、大規模プロジェクト&amp;lt;/q&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*namespace ブロックで定義&lt;br /&gt;
*exportで外側からアクセス可能なことを明示&lt;br /&gt;
*完全修飾名で呼び出す&lt;br /&gt;
 namespace NameA {&lt;br /&gt;
     export class Foo {&lt;br /&gt;
         name() {&lt;br /&gt;
             console.log(&amp;quot;NameA.Foo&amp;quot;);&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
     export function bar(){&lt;br /&gt;
         console.log(&amp;quot;NameA.bar()&amp;quot;);&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
 let foo = new NameA.Foo();&lt;br /&gt;
 foo.name();&lt;br /&gt;
 NameA.bar();&lt;br /&gt;
====名前空間のネスト====&lt;br /&gt;
 namespace NameB {&lt;br /&gt;
     export namespace NameC {&lt;br /&gt;
         export function bar(){&lt;br /&gt;
             console.log(&amp;quot;NameB.NameC.bar()&amp;quot;);&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
 NameB.NameC.bar();&lt;br /&gt;
&lt;br /&gt;
==変数・型==&lt;br /&gt;
===変数・定数===&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!変数宣言&lt;br /&gt;
!ブロックスコープ&lt;br /&gt;
!同じスコープでの重複宣言&lt;br /&gt;
!備考&lt;br /&gt;
|-&lt;br /&gt;
|var&lt;br /&gt;
|認識しない&lt;br /&gt;
|認める&lt;br /&gt;
|-&lt;br /&gt;
|let&lt;br /&gt;
|認識する&lt;br /&gt;
|認めない&lt;br /&gt;
|-&lt;br /&gt;
|const&lt;br /&gt;
|認識する&lt;br /&gt;
|認めない&lt;br /&gt;
|再代入不可&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
===型===&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!型&lt;br /&gt;
!説明&lt;br /&gt;
|-&lt;br /&gt;
|any&lt;br /&gt;
|任意、型がわからない場合。型チェックされずなんでもできてしまうため、できれば避ける。&lt;br /&gt;
|-&lt;br /&gt;
|unknown&lt;br /&gt;
|any同様任意の型をあらわすが、前もって型がわからない場合、anyではなくこちらの利用を推奨&lt;br /&gt;
|-&lt;br /&gt;
|number&lt;br /&gt;
|数値&lt;br /&gt;
|-&lt;br /&gt;
|bigint&lt;br /&gt;
|まるめ誤差なく大きな整数を扱うことができる(プラットフォームでサポートされているか確認が必要) let bi = 123n&lt;br /&gt;
|-&lt;br /&gt;
|string&lt;br /&gt;
|文字列&lt;br /&gt;
|-&lt;br /&gt;
|boolean&lt;br /&gt;
|真偽&lt;br /&gt;
|-&lt;br /&gt;
|symbol&lt;br /&gt;
|シンボル&lt;br /&gt;
|-&lt;br /&gt;
|object&lt;br /&gt;
|オブジェクト&lt;br /&gt;
|-&lt;br /&gt;
|T[]&lt;br /&gt;
|配列 number[],string[]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
====unknown型====&lt;br /&gt;
*値の比較、否定、typeof,instanceofが使用可能。以下のように利用する&lt;br /&gt;
 let foo: unknown;&lt;br /&gt;
 foo = 1;&lt;br /&gt;
 // let bar = foo + 2; // unknown のためエラー&lt;br /&gt;
 if (typeof foo == 'number') {&lt;br /&gt;
     let bar = foo + 2;  // OK&lt;br /&gt;
     console.log(bar);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
====undefinedも許可====&lt;br /&gt;
*string もしくは undefined&lt;br /&gt;
*aa 初期化時に必須だが、bbは指定しなくてもエラーとならない。&lt;br /&gt;
 interface hoge {&lt;br /&gt;
     aa : string,&lt;br /&gt;
     bb? : string&lt;br /&gt;
 }&lt;br /&gt;
 var h: hoge = {aa:'aaa'};&lt;br /&gt;
&lt;br /&gt;
===演算子===&lt;br /&gt;
*基本的に[[JavaScript]]と同じ&lt;br /&gt;
*https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators&lt;br /&gt;
&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!演算子&lt;br /&gt;
!説明&lt;br /&gt;
|-&lt;br /&gt;
|??&lt;br /&gt;
|[https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/Nullish_coalescing_operator Null合体] 左辺が null または undefined の場合に右の値を返し、それ以外の場合に左の値&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===文字列リテラル===&lt;br /&gt;
====`バッククオートで囲む(変数展開）====&lt;br /&gt;
*改行もそのまま&lt;br /&gt;
*${...} ...に変数、式を埋め込み&lt;br /&gt;
 class Program {&lt;br /&gt;
     static main() {&lt;br /&gt;
         let name: string = &amp;quot;Hiroto Yagi&amp;quot;;&lt;br /&gt;
         let age = 46;   // 型推論&lt;br /&gt;
         // age = &amp;quot;Hello&amp;quot;; // 数値型に文字列代入エラー&lt;br /&gt;
         let msg = null; // 初期値未指定、null指定など、any型と類推され型チェックは働かない&lt;br /&gt;
         msg = 100;      // noImplicitAny:true とすると、暗黙的 anyは許容しない&lt;br /&gt;
         msg = &amp;quot;Hello&amp;quot;;&lt;br /&gt;
     &lt;br /&gt;
         // テンプレート文字列&lt;br /&gt;
         console.log(`&lt;br /&gt;
         ${msg} &lt;br /&gt;
         my name is ${name} &lt;br /&gt;
         age ${age}&lt;br /&gt;
         ${new Date()}`);&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 Program.main();&lt;br /&gt;
=====結果=====&lt;br /&gt;
 &amp;amp;gt; node ./src/app.js&lt;br /&gt;
 &lt;br /&gt;
        Hello&lt;br /&gt;
        my name is Hiroto Yagi&lt;br /&gt;
        age 46&lt;br /&gt;
        toda Tue Nov 07 2017 18:59:23 GMT+0900 (東京 (標準時))&lt;br /&gt;
&lt;br /&gt;
===型アサーション===&lt;br /&gt;
====キャスト====&lt;br /&gt;
 function show(message: string) {&lt;br /&gt;
     console.log(`${message}`);&lt;br /&gt;
 }&lt;br /&gt;
 class TypeAssartion {&lt;br /&gt;
     static main() {&lt;br /&gt;
         // show(10);    // E[[R]][[R]]O[[R]]&lt;br /&gt;
         show(&amp;amp;lt;any&amp;amp;gt;10);  // OK&lt;br /&gt;
         show(10 as any); // as もOK&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
===コレクション/インターフェース===&lt;br /&gt;
*配列&lt;br /&gt;
*連想配列&lt;br /&gt;
*インデクスシグネチャはinterfaceとして事前定義可&lt;br /&gt;
 interface StringMap {&lt;br /&gt;
     [index:string]:string;&lt;br /&gt;
 }&lt;br /&gt;
 class Collection {&lt;br /&gt;
     static main() {&lt;br /&gt;
         // 配列&lt;br /&gt;
         let languages: string[] = ['java','C#','python'];&lt;br /&gt;
         console.log(languages);&lt;br /&gt;
 &lt;br /&gt;
         // 連想配列&lt;br /&gt;
         let fwMap: {[key:string]:string} = {&lt;br /&gt;
             'java':'[[Spring]]',&lt;br /&gt;
             '[[C#]]':'Asp.net',&lt;br /&gt;
             'python':'[[Django]]'&lt;br /&gt;
         };&lt;br /&gt;
         console.log(fwMap);&lt;br /&gt;
 &lt;br /&gt;
         // インデクスシグネチャはinterfaceとして事前定義可&lt;br /&gt;
         let fwMap2: StringMap = {&lt;br /&gt;
             'java':'[[Spring]]',&lt;br /&gt;
             '[[C#]]':'Asp.net',&lt;br /&gt;
             'python':'[[Django]]'&lt;br /&gt;
         };&lt;br /&gt;
         console.log(fwMap2);&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
===列挙===&lt;br /&gt;
 enum Animal {&lt;br /&gt;
     DOG,&lt;br /&gt;
     CAT,&lt;br /&gt;
     MOUSE,&lt;br /&gt;
     ELEPH[[ANT]]&lt;br /&gt;
 }&lt;br /&gt;
 enum Fruit {&lt;br /&gt;
     APPLE = &amp;quot;A&amp;quot;,&lt;br /&gt;
     O[[R]]ANGE = &amp;quot;O&amp;quot;,&lt;br /&gt;
     PAINAPPLE = &amp;quot;P&amp;quot;&lt;br /&gt;
 }&lt;br /&gt;
 class EnumSample {&lt;br /&gt;
     static main() {&lt;br /&gt;
         let mypet: Animal = Animal.DOG;&lt;br /&gt;
         // デフォルトで0からの数値が割り当てられる&lt;br /&gt;
         console.log(mypet);&lt;br /&gt;
         console.log(Animal[mypet]);&lt;br /&gt;
         &lt;br /&gt;
         let myfavarit: Fruit = Fruit.PAINAPPLE;&lt;br /&gt;
         // 列挙子に値を割り当てることも可能&lt;br /&gt;
         console.log(myfavarit);&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
=====結果=====&lt;br /&gt;
 0&lt;br /&gt;
 DOG&lt;br /&gt;
 P&lt;br /&gt;
===タプル===&lt;br /&gt;
*配列のサブタイプ&lt;br /&gt;
*固定長の配列を型づけ&lt;br /&gt;
 let tpl: [string, number, boolean] = ['Yagi', 46, true];&lt;br /&gt;
 console.log(`name:${tpl[0]} age:${tpl[1]} marriged:${tpl[2]}`);&lt;br /&gt;
&lt;br /&gt;
===合併型(共用型)と交差型===&lt;br /&gt;
*型の合併と交差を表現する特別な演算子が用意されている。&lt;br /&gt;
*合併 | と交差 &amp;amp;&lt;br /&gt;
*型エイリアスの例&lt;br /&gt;
 type Sales = { dept: string, product: string};&lt;br /&gt;
 type Engineer = { dept: string, project: string };&lt;br /&gt;
 &lt;br /&gt;
 type SalesOrEngineewOrBoth = Sales | Engineer;  // 合併&lt;br /&gt;
 type DeptPerson = Sales &amp;amp; Engineer; // 交差&lt;br /&gt;
&lt;br /&gt;
*合併型(共用型)使用例&lt;br /&gt;
 let data: string | boolean;&lt;br /&gt;
 data = 'foo';// OK&lt;br /&gt;
 data = true; // OK&lt;br /&gt;
 // data = 1; // NG&lt;br /&gt;
 &lt;br /&gt;
 let datas: (boolean | number)[] = [true, false, 1, 0];&lt;br /&gt;
&lt;br /&gt;
===型エイリアス===&lt;br /&gt;
*型の別名を定義できる&lt;br /&gt;
*ブロックスコープ&lt;br /&gt;
 type Age = number;&lt;br /&gt;
 let myage: Age = 48;&lt;br /&gt;
&lt;br /&gt;
*主にタプル、共用型に別名を付与。インターフェースでできる場合に使用しないほうがよい&lt;br /&gt;
 type ProfileTuple = [string, number, boolean];&lt;br /&gt;
 let me = ['yagi', 46, true];        &lt;br /&gt;
 console.log(`name:${me[0]} age:${me[1]} marriged:${me[2]}`);&lt;br /&gt;
&lt;br /&gt;
===文字列リテラル===&lt;br /&gt;
 type Season = 'spring' | 'summer' | 'autumn' | 'winter';&lt;br /&gt;
 class StringLiteralType {&lt;br /&gt;
     printSeason(s: Season) {&lt;br /&gt;
         console.log(s);&lt;br /&gt;
     }&lt;br /&gt;
     static main() {&lt;br /&gt;
         let me = new StringLiteralType();&lt;br /&gt;
         me.printSeason('summer');  // OK&lt;br /&gt;
         // me.printSeason('hoge'); // NG&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
===keyof演算子===&lt;br /&gt;
&lt;br /&gt;
==関数==&lt;br /&gt;
*function命令&lt;br /&gt;
*関数リテラル&lt;br /&gt;
*アロー関数&lt;br /&gt;
===関数、関数リテラル、アロー関数===&lt;br /&gt;
*関数リテラル(型推論)&lt;br /&gt;
*関数リテラル(型明示)&lt;br /&gt;
*アロー関数(ラムダ式)&lt;br /&gt;
[[Category:ラムダ]]&lt;br /&gt;
&lt;br /&gt;
 function squire(x: number, y: number) :number {&lt;br /&gt;
     return x * y;&lt;br /&gt;
 }&lt;br /&gt;
 class FunctionSample{&lt;br /&gt;
     static main() {&lt;br /&gt;
         // 関数の使用&lt;br /&gt;
         console.log(squire(8,8));&lt;br /&gt;
 &lt;br /&gt;
         // 関数リテラル(型推論)&lt;br /&gt;
         let m3 = function(x :number, y: number, z: number): number {&lt;br /&gt;
             return x * y * z;&lt;br /&gt;
         } ;&lt;br /&gt;
         console.log(m3(8,8,8));&lt;br /&gt;
 &lt;br /&gt;
         // 関数リテラル(型明示)&lt;br /&gt;
         let m2: (x: number, y: number) =&amp;amp;gt; number = function(x: number, y: number) {&lt;br /&gt;
             return x * y;&lt;br /&gt;
         };&lt;br /&gt;
         console.log(m2(9,9));&lt;br /&gt;
         &lt;br /&gt;
         // アロー関数(ラムダ式)&lt;br /&gt;
         // this は宣言された場所によって変わる&lt;br /&gt;
         let m22 = (x: number, y: number): number =&amp;amp;gt;  x * y;&lt;br /&gt;
         console.log(m22(5,5));&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
===引数の省略、デフォルト引数、可変長引数===&lt;br /&gt;
*TypeScriptでは宣言された引数はすべて必須&lt;br /&gt;
**引数を省略したい場合、仮引数の名前の後ろに ? を付与&lt;br /&gt;
*関数のデフォルト値を設定するには、仮引数の後に=デフォルト値&lt;br /&gt;
**デフォルト値には、式も利用できる&lt;br /&gt;
**明示的に undefined を渡した場合もデフォルト値が利用される &lt;br /&gt;
*可変長引数&lt;br /&gt;
**仮引数の前に、... とすることで可変長引数となる&lt;br /&gt;
**関数に1つ、最後のパラメータのみ&lt;br /&gt;
&lt;br /&gt;
 class FunctionApplySample {&lt;br /&gt;
     static main(){&lt;br /&gt;
         // TypeScript]は宣言された引数はすべて必須&lt;br /&gt;
         // 引数を省略したい場合、仮引数の名前の後ろに ? を付与&lt;br /&gt;
         let greet = function(message?: string){&lt;br /&gt;
             message = (message === undefined)?&amp;quot;hello&amp;quot;:message;&lt;br /&gt;
             console.log(message);&lt;br /&gt;
         }&lt;br /&gt;
         greet();&lt;br /&gt;
         greet(&amp;quot;good evening&amp;quot;);&lt;br /&gt;
     &lt;br /&gt;
         // 関数のデフォルト値を設定するには、仮引数の後に=デフォルト値&lt;br /&gt;
         // デフォルト値には、式も利用できる&lt;br /&gt;
         // 明示的に undefined を渡した場合もデフォルト値が利用される&lt;br /&gt;
         let greet2 = function(message: string=`hello ${new Date()}`) {&lt;br /&gt;
             console.log(message);&lt;br /&gt;
         }&lt;br /&gt;
         greet2();&lt;br /&gt;
         greet2(&amp;quot;good night&amp;quot;);&lt;br /&gt;
         greet2(undefined);&lt;br /&gt;
 &lt;br /&gt;
         // 可変長引数&lt;br /&gt;
         // 仮引数の前に、... とすることで可変長引数となる&lt;br /&gt;
         let sum = function(...nums: number[]):number {&lt;br /&gt;
             let ttl: number = 0;&lt;br /&gt;
             nums.forEach((value,index,array) =&amp;amp;gt; ttl += value);&lt;br /&gt;
             return ttl;&lt;br /&gt;
         }&lt;br /&gt;
         console.log(sum(1,2,3,4,5));&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
===thisの型を明示===&lt;br /&gt;
*thisが望むものであることを強制&lt;br /&gt;
*thisが関数シグネチャの一部として用いられる場合、予約語&lt;br /&gt;
 function printMonth(this:Date) {&lt;br /&gt;
     console.log(`${this.getMonth()+1}`);&lt;br /&gt;
 }&lt;br /&gt;
 printMonth.call(new Date());&lt;br /&gt;
 printMonth.call(1); // チェックでエラー表示される&lt;br /&gt;
&lt;br /&gt;
===関数のオーバーロード1===&lt;br /&gt;
#シグネチャのみの関数を用意&lt;br /&gt;
#具体的な実装を直後に定義&lt;br /&gt;
#実装の中で、typeof/instanceof を用いて型を判定し処理を記述 &lt;br /&gt;
&lt;br /&gt;
 function showMessage(value: number): void;&lt;br /&gt;
 function showMessage(value: boolean): void;&lt;br /&gt;
 function showMessage(value: any): void {&lt;br /&gt;
     let message: string | undefined;&lt;br /&gt;
     if (typeof value === 'number') {&lt;br /&gt;
         message = `${value} is number.`;&lt;br /&gt;
     }&lt;br /&gt;
     if (typeof value === 'boolean') {&lt;br /&gt;
         message = `${value} is boolean`;&lt;br /&gt;
     }&lt;br /&gt;
     console.log(message);&lt;br /&gt;
 }&lt;br /&gt;
  &lt;br /&gt;
 class FunctionApplySample2 {&lt;br /&gt;
     static main(){&lt;br /&gt;
         console.log(&amp;quot;*** 関数応用2 ***&amp;quot;);&lt;br /&gt;
         // 1.シグネチャのみの関数を用意&lt;br /&gt;
         // 2.具体的な実装を直後に定義&lt;br /&gt;
         // 3.実装の中で、typeof/instanceof を用いて型を判定し処理を記述&lt;br /&gt;
         showMessage(123);&lt;br /&gt;
         showMessage(false);&lt;br /&gt;
         showMessage(&amp;quot;Hello&amp;quot; as any);&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
===ユーザー定義型ガード===&lt;br /&gt;
*typeaof/instanceof は組み込みの型を絞り込むための機能&lt;br /&gt;
*is 演算子を使用して独自に定義可能&lt;br /&gt;
  function hoge(val:string | number) {&lt;br /&gt;
      if (isString(val)) {&lt;br /&gt;
          console.log(val.toUpperCase());&lt;br /&gt;
      } else {&lt;br /&gt;
          console.log(val);&lt;br /&gt;
      }&lt;br /&gt;
  }&lt;br /&gt;
  // boolean を返す関数の場合、型の絞り込みを行うことができる&lt;br /&gt;
  function isString(val: unknown): val is string { &lt;br /&gt;
      return typeof val === 'string';&lt;br /&gt;
  }&lt;br /&gt;
  hoge(1);&lt;br /&gt;
  hoge('a');&lt;br /&gt;
 *結果&lt;br /&gt;
 1&lt;br /&gt;
 A&lt;br /&gt;
&lt;br /&gt;
===関数のオーバーロード2===&lt;br /&gt;
*オーバーロードされた関数２つのシグネチャを宣言&lt;br /&gt;
*実装のシグネチャは２つの宣言を結合したもの&lt;br /&gt;
* 呼び出すときに結合されたシグネチャは見えない&lt;br /&gt;
&lt;br /&gt;
 // オーバーロードされた関数２つのシグネチャを宣言&lt;br /&gt;
 type ShowMessage = {&lt;br /&gt;
     (value: number):void,&lt;br /&gt;
     (value: boolean):void&lt;br /&gt;
 }    &lt;br /&gt;
 &lt;br /&gt;
 // 実装のシグネチャは２つの宣言を結合したもの &lt;br /&gt;
 let showMessage: ShowMessage = (&lt;br /&gt;
     value : number | boolean&lt;br /&gt;
 ) =&amp;gt; {&lt;br /&gt;
     let message: string | undefined;&lt;br /&gt;
     if (typeof value === 'number') {&lt;br /&gt;
         message = `${value} is number.`;&lt;br /&gt;
     }&lt;br /&gt;
     if (typeof value === 'boolean') {&lt;br /&gt;
         message = `${value} is boolean`;&lt;br /&gt;
     }&lt;br /&gt;
     console.log(message);&lt;br /&gt;
 }&lt;br /&gt;
*実行 &lt;br /&gt;
 // 呼び出すときに結合されたシグネチャは見えない&lt;br /&gt;
 showMessage(12);&lt;br /&gt;
 showMessage(true);&lt;br /&gt;
＊結果&lt;br /&gt;
 12 is number.&lt;br /&gt;
 true is boolean&lt;br /&gt;
&lt;br /&gt;
===ジェネレーターとイテレーター===&lt;br /&gt;
*ジェネレーター関数(function* )により生成&lt;br /&gt;
*生成されたオブジェクトは、反復可能なイテレーター&lt;br /&gt;
*利用者が要求したときだけ値を生成する&lt;br /&gt;
 function* increament(start: number) {&lt;br /&gt;
    　while (true) {&lt;br /&gt;
        start++;&lt;br /&gt;
        yield start;&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 let i = increament(10);&lt;br /&gt;
 console.log(i.next().value);&lt;br /&gt;
 console.log(i.next().value);&lt;br /&gt;
 console.log(i.next().value); &lt;br /&gt;
&lt;br /&gt;
*結果&lt;br /&gt;
 11&lt;br /&gt;
 12&lt;br /&gt;
 13&lt;br /&gt;
&lt;br /&gt;
==オブジェクト指向==&lt;br /&gt;
===クラス定義===&lt;br /&gt;
 class Person {&lt;br /&gt;
     // メンバー&lt;br /&gt;
     name: string;　// デフォルト public&lt;br /&gt;
     private _age: number; &lt;br /&gt;
 &lt;br /&gt;
     // 静的メンバー&lt;br /&gt;
     public static CHEAT_AGES: number = 2;&lt;br /&gt;
     &lt;br /&gt;
     // コンストラクター&lt;br /&gt;
     constructor(name: string, age: number){&lt;br /&gt;
         this.name = name;&lt;br /&gt;
         this._age = age;&lt;br /&gt;
     }&lt;br /&gt;
 &lt;br /&gt;
     // 以下のコンストラクターでメンバーの宣言と代入を省略できる&lt;br /&gt;
     // アクセス修飾子必須&lt;br /&gt;
     // constructor(public name: string, private _age: number) {&lt;br /&gt;
     // }&lt;br /&gt;
 &lt;br /&gt;
     // アクセッサー&lt;br /&gt;
     get age(): number {&lt;br /&gt;
         return this._age - Person.CHEAT_AGES;&lt;br /&gt;
     }&lt;br /&gt;
     set age(value: number) {&lt;br /&gt;
         this._age = value;&lt;br /&gt;
     }&lt;br /&gt;
 &lt;br /&gt;
     // メソッド&lt;br /&gt;
     print[[Profile]](){&lt;br /&gt;
         console.log(`name=${this.name},age=${this.age}`);&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
 console.log(Person.CHEAT_AGES);&lt;br /&gt;
 let me = new Person('Yagi', 46);&lt;br /&gt;
 //console.log(me.age); // NG&lt;br /&gt;
 me.print[[Profile]]();&lt;br /&gt;
 me.age = 50;&lt;br /&gt;
 me.print[[Profile]]();&lt;br /&gt;
=====結果=====&lt;br /&gt;
 2&lt;br /&gt;
 name=Yagi,age=44&lt;br /&gt;
 name=Yagi,age=48&lt;br /&gt;
&lt;br /&gt;
====コンストラクタ====&lt;br /&gt;
* コンストラクター&lt;br /&gt;
  name: string;　// デフォルト public&lt;br /&gt;
  private _age: number; &lt;br /&gt;
  constructor(name: string, age: number){&lt;br /&gt;
    this.name = name;&lt;br /&gt;
     this._age = age;&lt;br /&gt;
  }&lt;br /&gt;
 &lt;br /&gt;
*以下のコンストラクターでメンバーの宣言と代入を省略できる&lt;br /&gt;
**アクセス修飾子必須&lt;br /&gt;
 constructor(public name: string, private _age: number) &lt;br /&gt;
 }&lt;br /&gt;
====アクセス修飾子====&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!修飾子&lt;br /&gt;
!説明&lt;br /&gt;
|-&lt;br /&gt;
|public&lt;br /&gt;
|どこからでもアクセス可能。デフォルト。&lt;br /&gt;
|-&lt;br /&gt;
|protected&lt;br /&gt;
|このクラスと、サブプラスのインスタンスからアクセス可能。&lt;br /&gt;
|-&lt;br /&gt;
|private&lt;br /&gt;
|このクラスのインスタンスのみからアクセス可能&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===継承===&lt;br /&gt;
 class Guiter {&lt;br /&gt;
     constructor(public maker: string, public type: string){}&lt;br /&gt;
     print() {&lt;br /&gt;
         console.log(`${this.type} by ${this.maker}`);&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
 class Lespaul extends Guiter {&lt;br /&gt;
     constructor(){&lt;br /&gt;
         super(&amp;quot;Gibson&amp;quot;,&amp;quot;Lespaul&amp;quot;);&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
 (new Lespaul()).print();&lt;br /&gt;
===抽象クラス===&lt;br /&gt;
*直接インスタンス化しようとするとエラー&lt;br /&gt;
 // 抽象クラス&lt;br /&gt;
 abstract class Viecle {&lt;br /&gt;
     // 抽象メソッド&lt;br /&gt;
     abstract getEngineDisplacement(): number;&lt;br /&gt;
     printDisplacement() {&lt;br /&gt;
         console.log(`${this.getEngineDisplacement()}`);&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
 class Premacy extends Viecle {&lt;br /&gt;
     // 抽象メソッドのオーバーライド&lt;br /&gt;
     getEngineDisplacement(): number {&lt;br /&gt;
         return 2000;&lt;br /&gt;
     }&lt;br /&gt;
     // メソッドオーバーライド&lt;br /&gt;
     printDisplacement() {&lt;br /&gt;
         console.log(&amp;quot;******&amp;quot;);&lt;br /&gt;
         super.printDisplacement();&lt;br /&gt;
         console.log(&amp;quot;******&amp;quot;);&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
 (new Premacy()).printDisplacement();&lt;br /&gt;
&lt;br /&gt;
===インターフェース===&lt;br /&gt;
*型エイリアスと同様、インターフェースは型に名前をつけるための方法&lt;br /&gt;
**ほぼ同じだが、細かな差異もある。&lt;br /&gt;
*インラインで型を定義する必要がなくなる。&lt;br /&gt;
&lt;br /&gt;
 interface Color {&lt;br /&gt;
     // メソッドはすべて抽象メソッド&lt;br /&gt;
     // abstract 指定は不要&lt;br /&gt;
     get[[R]]GB(): string;&lt;br /&gt;
 }&lt;br /&gt;
 class [[R]]ed implements Color {&lt;br /&gt;
     get[[R]]GB(): string {&lt;br /&gt;
         return &amp;quot;#FF0000&amp;quot;;&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
 console.log((new [[R]]ed()).get[[R]]GB());&lt;br /&gt;
&lt;br /&gt;
====型とインターフェースの違い====&lt;br /&gt;
*型は右辺に任意の値をおけるがインターフェースはそうではない。&lt;br /&gt;
*以下のようなコードはインターフェースに書き換えられない&lt;br /&gt;
 type A = number;&lt;br /&gt;
 type B = A | string;&lt;br /&gt;
*インターフェースを拡張する場合、拡張元が拡張先に適用できるかチェックする。型エイリアスの場合拡張元と先を結合するために最善を尽くす&lt;br /&gt;
*同じスコープに同じ名前のインターフェースが複数存在する場合、自動的にマージされる。&lt;br /&gt;
&lt;br /&gt;
===super===&lt;br /&gt;
*親クラスのメソッドを呼び出すことができる。super.hoge();&lt;br /&gt;
*コンストラクターとして呼び出す。super();&lt;br /&gt;
&lt;br /&gt;
===構造的部分型(Structual subtyping)===&lt;br /&gt;
 class Hoge {&lt;br /&gt;
     constructor(public name: string, public age: number){}&lt;br /&gt;
 }&lt;br /&gt;
 class Spam {&lt;br /&gt;
     constructor(public name: string, public age: number){}&lt;br /&gt;
 }&lt;br /&gt;
 // 継承による明示的な互換性(Nominal subtyping)がなくても構造が一致していれば代入可能&lt;br /&gt;
 let h: Hoge = new Spam(&amp;quot;spam&amp;quot;,10);&lt;br /&gt;
 console.log(h);&lt;br /&gt;
&lt;br /&gt;
===型注釈としてのインターフェース===&lt;br /&gt;
*インターフェースを型注釈として利用できる&lt;br /&gt;
 interface Shape {&lt;br /&gt;
     // プロパティシグネチャ&lt;br /&gt;
     name: string;&lt;br /&gt;
     // メソッドシグネチャ&lt;br /&gt;
     draw():void;&lt;br /&gt;
 }&lt;br /&gt;
 let c : Shape = {&lt;br /&gt;
     name:'circle',&lt;br /&gt;
     draw() {&lt;br /&gt;
         console.log(`${this.name}:○`);&lt;br /&gt;
     } &lt;br /&gt;
 };&lt;br /&gt;
 c.draw();&lt;br /&gt;
&lt;br /&gt;
====オブジェクトリテラル====&lt;br /&gt;
*インターフェースを定義するまでもないが、型情報は明示しておきたい場合&lt;br /&gt;
 let t : { name: string, sides: number} = {name: 'triangle', sides: 3};&lt;br /&gt;
===型としてのthis===&lt;br /&gt;
*自分自身を返すことで、メソッドチェーンのような記述が可能となる&lt;br /&gt;
*派生クラスなど、呼び出し元のクラスに応じ型が変化する&lt;br /&gt;
 class StringBuilder {&lt;br /&gt;
     constructor(protected _value: string){&lt;br /&gt;
     }&lt;br /&gt;
     toString(): string {&lt;br /&gt;
         return this._value;&lt;br /&gt;
     }&lt;br /&gt;
     wrap(value: string) :string{&lt;br /&gt;
         return `${value}`;&lt;br /&gt;
     }&lt;br /&gt;
     // 自分自身を返すことで、メソッドチェーンのような記述が可能となる&lt;br /&gt;
     // 派生クラスなど、呼び出し元のクラスに応じ型が変化する&lt;br /&gt;
     append(value: string): this {&lt;br /&gt;
         this._value = this._value + this.wrap(value);&lt;br /&gt;
         return this;&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
 let buf = new StringBuilder('a');&lt;br /&gt;
 buf.append('b').append('c').append('d');&lt;br /&gt;
 console.log(buf.toString());&lt;br /&gt;
 &lt;br /&gt;
 class CsvBuilder extends StringBuilder {&lt;br /&gt;
     constructor(protected _value: string){&lt;br /&gt;
         super(_value);&lt;br /&gt;
     }&lt;br /&gt;
     wrap(value: string) {&lt;br /&gt;
         return `,${value}`;&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
 let csv = new CsvBuilder('a');&lt;br /&gt;
 csv.append('b').append('c').append('d');&lt;br /&gt;
 console.log(csv.toString());&lt;br /&gt;
=====出力=====&lt;br /&gt;
 abcd&lt;br /&gt;
 a,b,c,d&lt;br /&gt;
&lt;br /&gt;
===ジェネリック===&lt;br /&gt;
 let numary: Array&amp;amp;lt;number&amp;amp;gt; = [1,2,3,5,8];&lt;br /&gt;
====ジェネリック型の定義 ====&lt;br /&gt;
*StringBuilder型は、上記で定義参照&lt;br /&gt;
*型引数に制約を付与する場合、extends を使用する。&lt;br /&gt;
*使用しなければ、あらゆる型を渡すことができる&lt;br /&gt;
&lt;br /&gt;
 class XmlBuilder extends StringBuilder {&lt;br /&gt;
     constructor(protected _value: string){&lt;br /&gt;
         super(_value);&lt;br /&gt;
     }&lt;br /&gt;
     wrap(value: string) {&lt;br /&gt;
         return `&amp;amp;lt;value&amp;amp;gt;${value}&amp;amp;lt;/value&amp;amp;gt;`;&lt;br /&gt;
     }&lt;br /&gt;
     toString(): string {&lt;br /&gt;
         return `&amp;amp;lt;values&amp;amp;gt;${this._value}&amp;amp;lt;/values&amp;amp;gt;`;&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 // 型引数に制約を付与する場合、extends を使用する。&lt;br /&gt;
 // 使用しなければ、あらゆる型を渡すことができる&lt;br /&gt;
 class [[R]]eport&amp;amp;lt;T extends StringBuilder&amp;amp;gt; {&lt;br /&gt;
     builder: T;&lt;br /&gt;
     getBuilder(): T {&lt;br /&gt;
         return this.builder;&lt;br /&gt;
     }&lt;br /&gt;
     addLine(line: string) {&lt;br /&gt;
         this.getBuilder().append(line);&lt;br /&gt;
     }&lt;br /&gt;
     report() {&lt;br /&gt;
         console.log(this.getBuilder().toString());&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
 let rep = new [[R]]eport&amp;amp;lt;XmlBuilder&amp;amp;gt;();&lt;br /&gt;
 //　ジェネリック型に具体的なインスタンスを紐づけ&lt;br /&gt;
 rep.builder = new XmlBuilder('');&lt;br /&gt;
 rep.addLine(&amp;quot;this is lesson.&amp;quot;);&lt;br /&gt;
 rep.addLine(&amp;quot;of [[TypeScript]].&amp;quot;)&lt;br /&gt;
 rep.report();&lt;br /&gt;
=====出力例=====&lt;br /&gt;
 &amp;amp;lt;values&amp;amp;gt;&amp;amp;lt;value&amp;amp;gt;this is lesson.&amp;amp;lt;/value&amp;amp;gt;&amp;amp;lt;value&amp;amp;gt;of [[TypeScript]].&amp;amp;lt;/value&amp;amp;gt;&amp;amp;lt;/values&amp;amp;gt;&lt;br /&gt;
&lt;br /&gt;
====ジェネリックメソッド====&lt;br /&gt;
 function reverse&amp;amp;lt;T&amp;amp;gt;(data: T[]): T[] {&lt;br /&gt;
     let ary: T[] = new Array();&lt;br /&gt;
 &lt;br /&gt;
     let j=0;&lt;br /&gt;
     for(let i=data.length-1; i&amp;amp;gt;=0; i--) {&lt;br /&gt;
         ary[j++] = data[i];&lt;br /&gt;
     }&lt;br /&gt;
     return ary;&lt;br /&gt;
 }&lt;br /&gt;
 console.log(reverse&amp;amp;lt;number&amp;amp;gt;([1,2,3,4]));&lt;br /&gt;
 console.log(reverse&amp;amp;lt;string&amp;amp;gt;([&amp;quot;a&amp;quot;,&amp;quot;b&amp;quot;,&amp;quot;c&amp;quot;,&amp;quot;d&amp;quot;]));&lt;br /&gt;
=====出力例=====&lt;br /&gt;
 [ 4, 3, 2, 1 ]&lt;br /&gt;
 [ 'd', 'c', 'b', 'a' ]&lt;br /&gt;
&lt;br /&gt;
===サンプル===&lt;br /&gt;
{{ref app.ts}}&lt;br /&gt;
&lt;br /&gt;
==非同期プログラミングと並行・並列処理==&lt;br /&gt;
===ObservableとPromise===&lt;br /&gt;
*https://angular.jp/guide/comparing-observables&lt;br /&gt;
====比較====&lt;br /&gt;
*Observable は宣言型で、購読するまで処理が開始されない。Promise は作成時に直ちに実行される。&lt;br /&gt;
**結果が必要なときにいつでも実行できるレシピを定義するために、Observable が役立つ。&lt;br /&gt;
*Observable は多くの値を提供します。Promise は1つです。&lt;br /&gt;
**時間の経過とともに複数の値を取得するのには Observable が有効&lt;br /&gt;
*Observable は、連鎖とサブスクリプションを区別します。Promise は .then() 句しかありません。&lt;br /&gt;
**Observableは、作業を実行させることなく、システムの他の部分で使用される複雑な変換レシピを作成するのに便利&lt;br /&gt;
*Observable の subscribe() はエラーを処理します。Promise は子の Promise にエラーをプッシュします。&lt;br /&gt;
**Observable は集中管理され、予測可能なエラー処理に役立&lt;br /&gt;
&lt;br /&gt;
===Observable===&lt;br /&gt;
*RxJsライブラリ&lt;br /&gt;
*https://angular.jp/guide/rx-library&lt;br /&gt;
&lt;br /&gt;
リアクティブプログラミングは、データストリームと変更の伝播に関する非同期プログラミングのパラダイムです。&lt;br /&gt;
RxJS (Reactive Extensions for JavaScript) は、非同期またはコールバックベースのコード (RxJS Docs) の作成を容易にする &lt;br /&gt;
observables を使用したリアクティブプログラミング用のライブラリ&lt;br /&gt;
&lt;br /&gt;
*非同期処理の既存のコードを observables に変換する&lt;br /&gt;
*ストリーム内の値を反復処理する&lt;br /&gt;
*異なる型への値のマッピング&lt;br /&gt;
*ストリームのフィルタリング&lt;br /&gt;
*複数のストリームの作成&lt;br /&gt;
&lt;br /&gt;
====Observable 作成関数====&lt;br /&gt;
ベント、タイマー、promise などから observables を作成するプロセスを簡素化&lt;br /&gt;
====promise から observable を作成====&lt;br /&gt;
 import { from } from 'rxjs';&lt;br /&gt;
 &lt;br /&gt;
 // promise から Observable を作成&lt;br /&gt;
 const data = from(fetch('/api/endpoint'));&lt;br /&gt;
 // 非同期の結果の購読を開始&lt;br /&gt;
 data.subscribe({&lt;br /&gt;
   next(response) { console.log(response); },&lt;br /&gt;
   error(err) { console.error('Error: ' + err); },&lt;br /&gt;
   complete() { console.log('Completed'); }&lt;br /&gt;
 });&lt;br /&gt;
&lt;br /&gt;
====カウンターから observable を作成する====&lt;br /&gt;
 import { interval } from 'rxjs';&lt;br /&gt;
 &lt;br /&gt;
 // 一定間隔でで値を発行するObservable を作成&lt;br /&gt;
 const secondsCounter = interval(1000);&lt;br /&gt;
 // 発行される値の購読を開始&lt;br /&gt;
 secondsCounter.subscribe(n =&amp;gt;&lt;br /&gt;
   console.log(`It's been ${n} seconds since subscribing!`));&lt;br /&gt;
&lt;br /&gt;
====イベントから observable を作成する====&lt;br /&gt;
 import { fromEvent } from 'rxjs';&lt;br /&gt;
 &lt;br /&gt;
 const el = document.getElementById('my-element');&lt;br /&gt;
 &lt;br /&gt;
 // マウスの移動を発行する Observable の作成&lt;br /&gt;
 const mouseMoves = fromEvent(el, 'mousemove');&lt;br /&gt;
 &lt;br /&gt;
 // マウス移動イベントを購読開始 &lt;br /&gt;
 const subscription = mouseMoves.subscribe((evt: MouseEvent) =&amp;gt; {&lt;br /&gt;
   console.log(`Coords: ${evt.clientX} X ${evt.clientY}`);&lt;br /&gt;
 &lt;br /&gt;
   // スクリーンの左端をマウスが越えたら購読中止&lt;br /&gt;
   if (evt.clientX &amp;lt; 40 &amp;amp;&amp;amp; evt.clientY &amp;lt; 40) {&lt;br /&gt;
     subscription.unsubscribe();&lt;br /&gt;
   }&lt;br /&gt;
 });&lt;br /&gt;
&lt;br /&gt;
====AJAX リクエストから observable を作成====&lt;br /&gt;
&lt;br /&gt;
 import { ajax } from 'rxjs/ajax';&lt;br /&gt;
 &lt;br /&gt;
 // AJAXリクエストを生成する Observable の作成&lt;br /&gt;
 const apiData = ajax('/api/data');&lt;br /&gt;
 // リクエストの生成を購読&lt;br /&gt;
 apiData.subscribe(res =&amp;gt; console.log(res.status, res.response));&lt;br /&gt;
&lt;br /&gt;
===Promise===&lt;br /&gt;
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise&lt;br /&gt;
*非同期の作業を抽象化して、それらを組み立てたり順番に並べる方法&lt;br /&gt;
 import { isNumber } from &amp;quot;util&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
 function getPromise(waittime:string): Promise&amp;lt;string&amp;gt; {&lt;br /&gt;
     return new Promise&amp;lt;string&amp;gt;((resolve, reject) =&amp;gt; {&lt;br /&gt;
         if (isNaN(Number(waittime)) ) {&lt;br /&gt;
             reject(&amp;quot;error&amp;quot;);&lt;br /&gt;
         } else {&lt;br /&gt;
             const wt = parseInt(waittime);&lt;br /&gt;
             setTimeout(() =&amp;gt; {&lt;br /&gt;
                 resolve(`WAIT ${wt}`);&lt;br /&gt;
             }, wt);&lt;br /&gt;
         }&lt;br /&gt;
     });&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 function usePromise() {&lt;br /&gt;
     getPromise(&amp;quot;2000&amp;quot;)&lt;br /&gt;
         .then((v) =&amp;gt; {&lt;br /&gt;
             console.log(v);&lt;br /&gt;
         })&lt;br /&gt;
         .catch((e) =&amp;gt; {&lt;br /&gt;
             console.log(e);&lt;br /&gt;
         });&lt;br /&gt;
     getPromise(&amp;quot;aaaaa&amp;quot;)&lt;br /&gt;
         .then((v) =&amp;gt; {&lt;br /&gt;
             console.log(v);&lt;br /&gt;
         })&lt;br /&gt;
         .catch((e) =&amp;gt; {&lt;br /&gt;
             console.log(e);&lt;br /&gt;
         });&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 usePromise();&lt;br /&gt;
*結果&lt;br /&gt;
非同期で呼び出すため、呼び出し結果と出力順序が入れ替わる&lt;br /&gt;
 error&lt;br /&gt;
 WAIT 2000&lt;br /&gt;
&lt;br /&gt;
===async , await===&lt;br /&gt;
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function&lt;br /&gt;
*Promiseはとてもポピュラーなパターンなので、JavaScript(TypeScript)では独自の構文が用意されている。&lt;br /&gt;
*await は .then に対するシンタックスシュガーと言える&lt;br /&gt;
*await を使ってPromiseを待機する場合、async ブロックの中で行う&lt;br /&gt;
*ラムダの場合 hoge(async ()=&amp;gt; {})&lt;br /&gt;
 import { isNumber } from &amp;quot;util&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
 function getPromise(waittime:string): Promise&amp;lt;string&amp;gt; {&lt;br /&gt;
     return new Promise&amp;lt;string&amp;gt;((resolve, reject) =&amp;gt; {&lt;br /&gt;
         if (isNaN(Number(waittime)) ) {&lt;br /&gt;
             reject(&amp;quot;error&amp;quot;);&lt;br /&gt;
         } else {&lt;br /&gt;
             const wt = parseInt(waittime);&lt;br /&gt;
             setTimeout(() =&amp;gt; {&lt;br /&gt;
                 resolve(`WAIT ${wt}`);&lt;br /&gt;
             }, wt);&lt;br /&gt;
         }&lt;br /&gt;
     });&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 async function usePromise() {&lt;br /&gt;
     try {&lt;br /&gt;
         let result = await getPromise(&amp;quot;2000&amp;quot;)&lt;br /&gt;
         console.log(result);&lt;br /&gt;
         let result2 = await getPromise(&amp;quot;aaaa&amp;quot;)&lt;br /&gt;
         console.log(result2);&lt;br /&gt;
     } catch(e) {&lt;br /&gt;
         console.log(e);&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 usePromise();&lt;br /&gt;
*結果&lt;br /&gt;
await で同期されるため、呼び出し順に出力される&lt;br /&gt;
 WAIT 2000&lt;br /&gt;
 error&lt;br /&gt;
&lt;br /&gt;
===非同期ストリーム===&lt;br /&gt;
*一般的には、イベントエミッター(Node.jsでは、EventEmitter)、リアクティブプログラミングライブラリー([https://www.npmjs.com/package/rxjs RxJS]、[https://github.com/mostjs/core MostJS] など)を利用する&lt;br /&gt;
*2つの違いはコールバックとPromiseに似ている。イベントエミッターは軽量、迅速であり、リアクティブプログラミングは強力でイベントストリームを組み立てたり並べたりが可能&lt;br /&gt;
===マルチスレッディング===&lt;br /&gt;
*上記までは非同期処理&lt;br /&gt;
*マルチスレッドによる並列処理を行う&lt;br /&gt;
*[[TypeScript 並列処理]]&lt;br /&gt;
&lt;br /&gt;
==Node.jsを使う==&lt;br /&gt;
[[Node.js]]&lt;br /&gt;
&lt;br /&gt;
*https://ics.media/entry/4682/&lt;br /&gt;
*[https://www.typea.info/blog/index.php/2020/07/23/typescript_node_environment/ ローカルにTypeScriptの動作確認環境をNode.jsで作成]&lt;br /&gt;
===環境構築===&lt;br /&gt;
*作業ディレクトリで実行&lt;br /&gt;
 $ npm init -y&lt;br /&gt;
 Wrote to /Users/hirotoyagi/Workspaces/Node/sample/package.json:&lt;br /&gt;
 &lt;br /&gt;
 {&lt;br /&gt;
   &amp;quot;name&amp;quot;: &amp;quot;sample&amp;quot;,&lt;br /&gt;
   &amp;quot;version&amp;quot;: &amp;quot;1.0.0&amp;quot;,&lt;br /&gt;
   &amp;quot;description&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
   &amp;quot;main&amp;quot;: &amp;quot;index.js&amp;quot;,&lt;br /&gt;
   &amp;quot;scripts&amp;quot;: {&lt;br /&gt;
     &amp;quot;test&amp;quot;: &amp;quot;echo \&amp;quot;Error: no test specified\&amp;quot; &amp;amp;&amp;amp; exit 1&amp;quot;&lt;br /&gt;
   },&lt;br /&gt;
   &amp;quot;keywords&amp;quot;: [],&lt;br /&gt;
   &amp;quot;author&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
   &amp;quot;license&amp;quot;: &amp;quot;ISC&amp;quot;&lt;br /&gt;
 }&lt;br /&gt;
*package.jsonを編集&lt;br /&gt;
  &amp;quot;scripts&amp;quot;: {&lt;br /&gt;
    &amp;quot;build&amp;quot;: &amp;quot;tsc&amp;quot;,&lt;br /&gt;
    &amp;quot;watch&amp;quot;: &amp;quot;tsc --watch&amp;quot;&lt;br /&gt;
  },&lt;br /&gt;
*TypeScriptのインストールと確認&lt;br /&gt;
 $ npm install --save-dev typescript&lt;br /&gt;
 $ node_modules/.bin/tsc --version&lt;br /&gt;
 Version 3.9.7&lt;br /&gt;
*初期化&lt;br /&gt;
 $ node_modules/.bin/tsc --init&lt;br /&gt;
 message TS6071: Successfully created a tsconfig.json file.&lt;br /&gt;
*[[Node.js]]の型定義をインストール&lt;br /&gt;
 $ npm install --save @types/node&lt;br /&gt;
*tsをTypeScriptで記述しjsにコンパイル&lt;br /&gt;
app.ts&lt;br /&gt;
 console.log(&amp;quot;test&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
 $ npm run build&lt;br /&gt;
*app.js が生成されるので、Nodeで実行&lt;br /&gt;
app.js&lt;br /&gt;
 &amp;quot;use strict&amp;quot;;&lt;br /&gt;
 console.log(&amp;quot;test&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
 $ node app&lt;br /&gt;
&lt;br /&gt;
==[[Tips]]==&lt;br /&gt;
===TypeDoc===&lt;br /&gt;
*https://qiita.com/Mic-U/items/961ce4e0c2a1def1dbd3&lt;br /&gt;
*https://qiita.com/ConquestArrow/items/eb4a0dfb13497be4d6a3&lt;br /&gt;
====インストール====&lt;br /&gt;
 &amp;amp;gt; [[npm]] install typedoc -g&lt;br /&gt;
====作成====&lt;br /&gt;
 &amp;amp;gt; typedoc --out ./docs/ ./src/ --module commonjs&lt;br /&gt;
&lt;br /&gt;
===ASP.NET===&lt;br /&gt;
*[https://docs.microsoft.com/ja-jp/visualstudio/javascript/tutorial-aspnet-with-typescript?view=vs-2019 TypeScript を使用した ASP.NET Core アプリの作成]&lt;br /&gt;
&lt;br /&gt;
===GAE===&lt;br /&gt;
*https://cloud.google.com/appengine/docs/standard/nodejs/running-custom-build-step?hl=ja&lt;br /&gt;
[[Google App Engine]]&lt;br /&gt;
&lt;br /&gt;
{{amazon|B0733113NK}}&lt;br /&gt;
===配列===&lt;br /&gt;
====[[JavaScript Array|配列でなければ配列に、配列ならそのまま（もしくは追加)]]====&lt;br /&gt;
*[[JavaScript Array|配列でなければ配列に、配列ならそのまま（もしくは追加)]]&lt;br /&gt;
&lt;br /&gt;
[[category:プログラミング言語]]&lt;/div&gt;</summary>
		<author><name>Piroto</name></author>
		
	</entry>
	<entry>
		<id>https://www.typea.info/tips_/index.php?title=MUI&amp;diff=35327</id>
		<title>MUI</title>
		<link rel="alternate" type="text/html" href="https://www.typea.info/tips_/index.php?title=MUI&amp;diff=35327"/>
		<updated>2024-10-05T05:48:17Z</updated>

		<summary type="html">&lt;p&gt;Piroto: /* インストール */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[React]] | [[Next.js]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*https://mui.com/&lt;br /&gt;
*Material UI (MUI) はReactアプリで利用できるコンポーネントを集めたライブラリ&lt;br /&gt;
&lt;br /&gt;
==主なコンポーネント==&lt;br /&gt;
*MUI Core　： 基本コンポーネント(無償)&lt;br /&gt;
*MUI X :　より複雑なユースケースに対応下コンポーネント群(一部有償)&lt;br /&gt;
*Templates : MUIベースで構築されたテンプレート群&lt;br /&gt;
&lt;br /&gt;
==インストール==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ npm install @mui/material @mui/icons-material @emotion/react @emotion/styled&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*内部的に[https://emotion.sh/docs/introduction Emotion](フレームワークにとらわれず使うことができるCSS in JSのフレームワーク)を利用している&lt;br /&gt;
&lt;br /&gt;
==使用==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import { Button } from '@mui/material';&lt;br /&gt;
   :&lt;br /&gt;
&lt;br /&gt;
&amp;amp;lt;Button variant=&amp;quot;text&amp;quot;&amp;amp;gt;Text&amp;amp;lt;/Button&amp;amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Piroto</name></author>
		
	</entry>
	<entry>
		<id>https://www.typea.info/tips_/index.php?title=MUI&amp;diff=35326</id>
		<title>MUI</title>
		<link rel="alternate" type="text/html" href="https://www.typea.info/tips_/index.php?title=MUI&amp;diff=35326"/>
		<updated>2024-10-05T05:43:26Z</updated>

		<summary type="html">&lt;p&gt;Piroto: /* インストール */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[React]] | [[Next.js]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*https://mui.com/&lt;br /&gt;
*Material UI (MUI) はReactアプリで利用できるコンポーネントを集めたライブラリ&lt;br /&gt;
&lt;br /&gt;
==主なコンポーネント==&lt;br /&gt;
*MUI Core　： 基本コンポーネント(無償)&lt;br /&gt;
*MUI X :　より複雑なユースケースに対応下コンポーネント群(一部有償)&lt;br /&gt;
*Templates : MUIベースで構築されたテンプレート群&lt;br /&gt;
&lt;br /&gt;
==インストール==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ npm install @mui/material @mui/icons-material @emotion/react @emotion/styled&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*内部的に[https://emotion.sh/docs/introduction Emotion](フレームワークにとらわれず使うことができるCSS in JSのフレームワーク)を利用している&lt;/div&gt;</summary>
		<author><name>Piroto</name></author>
		
	</entry>
	<entry>
		<id>https://www.typea.info/tips_/index.php?title=MUI&amp;diff=35325</id>
		<title>MUI</title>
		<link rel="alternate" type="text/html" href="https://www.typea.info/tips_/index.php?title=MUI&amp;diff=35325"/>
		<updated>2024-10-05T05:40:55Z</updated>

		<summary type="html">&lt;p&gt;Piroto: /* 主なコンポーネント */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[React]] | [[Next.js]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*https://mui.com/&lt;br /&gt;
*Material UI (MUI) はReactアプリで利用できるコンポーネントを集めたライブラリ&lt;br /&gt;
&lt;br /&gt;
==主なコンポーネント==&lt;br /&gt;
*MUI Core　： 基本コンポーネント(無償)&lt;br /&gt;
*MUI X :　より複雑なユースケースに対応下コンポーネント群(一部有償)&lt;br /&gt;
*Templates : MUIベースで構築されたテンプレート群&lt;br /&gt;
&lt;br /&gt;
==インストール==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ npm install @mui/material @mui/icons-material @emotion/react @emotion/styled&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Piroto</name></author>
		
	</entry>
	<entry>
		<id>https://www.typea.info/tips_/index.php?title=Next.js&amp;diff=35324</id>
		<title>Next.js</title>
		<link rel="alternate" type="text/html" href="https://www.typea.info/tips_/index.php?title=Next.js&amp;diff=35324"/>
		<updated>2024-10-05T05:38:28Z</updated>

		<summary type="html">&lt;p&gt;Piroto: /* フォント */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[React]] | [[MUI]] |&lt;br /&gt;
&lt;br /&gt;
{{amazon|4815619484}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Reactは、あくまでUI部分のみ&lt;br /&gt;
*本格的なアプリ開発には周辺領域を担うためのフレームワークが必要&lt;br /&gt;
*Reactベースのフレームワークとしてデファクトスタンダードと言える存在&lt;br /&gt;
*主なライブラリ&lt;br /&gt;
**ファイルシステムベースの設定レスルーター&lt;br /&gt;
**サーバーコンポーネント&lt;br /&gt;
**データ取得用fetchメソッド&lt;br /&gt;
**リソース組み込みの自動最適化&lt;br /&gt;
**CSSフレームワーク、Tailwind　CSSへの標準対応&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=導入=&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
newdelhi:Workspaces piroto$ npx create-next-app@latest&lt;br /&gt;
Need to install the following packages:&lt;br /&gt;
create-next-app@14.2.14&lt;br /&gt;
Ok to proceed? (y) y&lt;br /&gt;
&lt;br /&gt;
✔ What is your project named? … first-nextjs-app&lt;br /&gt;
✔ Would you like to use TypeScript? … No / Yes&lt;br /&gt;
✔ Would you like to use ESLint? … No / Yes&lt;br /&gt;
✔ Would you like to use Tailwind CSS? … No / Yes&lt;br /&gt;
✔ Would you like to use `src/` directory? … No / Yes&lt;br /&gt;
✔ Would you like to use App Router? (recommended) … No / Yes&lt;br /&gt;
✔ Would you like to customize the default import alias (@/*)? … No / Yes&lt;br /&gt;
Creating a new Next.js app in /Users/piroto/Workspaces/first-nextjs-app.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==実行==&lt;br /&gt;
===開発===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
npm run dev&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Start_next_js.png | 300px]]&lt;br /&gt;
&lt;br /&gt;
===本番ビルド＋実行===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
npm run build&lt;br /&gt;
npm start&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==App Router==&lt;br /&gt;
*React Routerとは異なる独自のルーターを標準で提供&lt;br /&gt;
*コンポーネントそのものはReactと変わらない&lt;br /&gt;
&lt;br /&gt;
===2種類のルーター===&lt;br /&gt;
&lt;br /&gt;
*Pages Router : 旧来から提供されている&lt;br /&gt;
*App Router : Next.js 13から導入された新しいルーター(推奨)&lt;br /&gt;
&lt;br /&gt;
====App Router====&lt;br /&gt;
*フォルダベースのルーター&lt;br /&gt;
*ルート定義不要、フォルダ階層に準じてリクエストパスとコンポーネント(.jsファイル)との対応関係が決まる&lt;br /&gt;
*page.jsはファイル名も固定でフォルダー構造だけでリクエストパスが決定される&lt;br /&gt;
&lt;br /&gt;
=====アプリ共通の外枠=====&lt;br /&gt;
*layout.js&lt;br /&gt;
*&amp;amp;lt;html&amp;amp;gt;、&amp;amp;lt;body&amp;amp;gt; 要素が存在し、個々のページを埋め込むため chilrenプロパティを引用していることが条件&lt;br /&gt;
&lt;br /&gt;
===ルートパラメータ===&lt;br /&gt;
*[名前] ： 単一パラメータ&lt;br /&gt;
*[...名前] : キャッチオールセグメント&lt;br /&gt;
*&amp;lt;nowiki&amp;gt;[[...名前]]&amp;lt;/nowiki&amp;gt; : 省略可能なキャッチオールセグメント&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ App Routerのルートパラメータ&lt;br /&gt;
|-&lt;br /&gt;
! フォルダ階層 !! 対応リクエスト !! パラメータ&lt;br /&gt;
|-&lt;br /&gt;
| /app/hoge/[id]/page.js || /hoge/001 || { id : '001' }&lt;br /&gt;
|-&lt;br /&gt;
| /app/foo/[...keys]/page.js || /foo/aaa/bbb || { keys: ['aaa', 'bbb'] }&lt;br /&gt;
|-&lt;br /&gt;
| /app/bar/&amp;lt;nowiki&amp;gt;[[...keys]]&amp;lt;/nowiki&amp;gt;/page.js || /bar || {}&lt;br /&gt;
|-&lt;br /&gt;
| 〃 || /bar/aaa/bbb || { keys: ['aaa', 'bbb'] }&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Tailwind CSS==&lt;br /&gt;
*https://tailwindcss.com/&lt;br /&gt;
*ユーティリティファーストをコンセプトに開発されたCSSフレームワーク&lt;br /&gt;
*ユーティリティを組み合わせてデザインを作るので独自のスタイルを作りやすく細かな調整もしやすいメリット&lt;br /&gt;
*標準のサイズ、カラーなどは用意されている&lt;br /&gt;
&lt;br /&gt;
[https://tailwindcsscheatsheet.com/ Cheat Sheet]&lt;br /&gt;
&lt;br /&gt;
*Tailwind　CSSによるスタイルを適用&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import &amp;quot;./globals.css&amp;quot;;&lt;br /&gt;
    :&lt;br /&gt;
&lt;br /&gt;
&amp;amp;lt;ul className=&amp;quot;fle bg-blue-600 mb-4 pl-2&amp;quot;&amp;amp;gt;...&amp;amp;lt;/ul&amp;amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Prisma==&lt;br /&gt;
*JavaScriptアプリからデータベース操作を取り持つO/Rマッパー&lt;br /&gt;
===インストール===&lt;br /&gt;
*成功すると以下のファイルが生成される&lt;br /&gt;
**.env : 環境変数ファイル、gitignore に追加する&lt;br /&gt;
** prisma/schema.prisma : Prismaのスキーマファイル&lt;br /&gt;
&lt;br /&gt;
sqliteでの構成例&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ npm install prisma --save-dev&lt;br /&gt;
 $ npx prisma init --datasource-provider sqlite&lt;br /&gt;
 warn You already have a .gitignore file. Don't forget to add `.env` in it to not commit any private information.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===データモデルの定義===&lt;br /&gt;
*prisma/schema.prisma に追記&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
model　reviews {&lt;br /&gt;
  id          String @id&lt;br /&gt;
  title       String&lt;br /&gt;
  author      String&lt;br /&gt;
  price       Int&lt;br /&gt;
  publlisher  String&lt;br /&gt;
  published   String&lt;br /&gt;
  image       String&lt;br /&gt;
  read        DateTime  @default(now())&lt;br /&gt;
  memo        String&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*DBに反映&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ npx prisma db push&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Prisma Studio(Webベース管理ツール)で確認&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ npx prisma studio&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==サーバーアクション==&lt;br /&gt;
*Next.js内蔵の仕組み&lt;br /&gt;
*ページコンポーネント、イベントハンドラー、&amp;amp;lt;form&amp;amp;lt;要素のaction属性などからサーバーコードを呼び出す仕組み&lt;br /&gt;
*サーバーとのやりとりに際し、fetchなどの非同期通信コードの不要となり、例えばコンポーネントからデータベースを操作するにも直感的なコードを記述できる&lt;br /&gt;
*現時点ではα版&lt;br /&gt;
&lt;br /&gt;
===有効化===&lt;br /&gt;
&lt;br /&gt;
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]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
const nextConfig = {&lt;br /&gt;
    experimental: {&lt;br /&gt;
        serverActions: true&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==実装==&lt;br /&gt;
&lt;br /&gt;
===ルートレイアウト===&lt;br /&gt;
====アプリ内のリンクにはLinkコンポーネントを利用====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import Link from &amp;quot;next/link&amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
規定で以下のようなコンポーネントが用意されており、アプリ内リソースを効率的に利用できる&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ コンポーネント&lt;br /&gt;
|-&lt;br /&gt;
! コンポーネント !! 概要&lt;br /&gt;
|-&lt;br /&gt;
| &amp;amp;lt;Link&amp;amp;gt; || リンクを生成&lt;br /&gt;
|-&lt;br /&gt;
| &amp;amp;lt;Script&amp;amp;gt; || スクリプトのロード&lt;br /&gt;
|-&lt;br /&gt;
| &amp;amp;lt;Image&amp;amp;gt; || 画像を表示&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
====メタデータ====&lt;br /&gt;
*メタデータを定義しておくことで、個々のページに適切なヘッダーなどを埋め込める&lt;br /&gt;
*複数箇所で宣言された場合、シャローマージされる&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
export const metadata: Metadata = {&lt;br /&gt;
  title: &amp;quot;Reading Recorder&amp;quot;,&lt;br /&gt;
  description: &amp;quot;自分が読んだ書籍の記録を残す&amp;quot;,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*generateMetadata関数を利用しデータベースなどから取得した結果を元に動的に生成も可能&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
export async function generateMetadata({ params, searchParams }) {&lt;br /&gt;
    :&lt;br /&gt;
    return {&lt;br /&gt;
        title : result.title,&lt;br /&gt;
            :&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==フォント==&lt;br /&gt;
*Googleフォント(無償フォントのディレクトリサービス)を有効化&lt;br /&gt;
*具体的なフォントはGoogleフォントから自由に選択できるが一般的にはバリアブルフォント推奨(下例ではInconsolata)&lt;br /&gt;
*フォントはファイルサイズが大きいので、subsetで利用する文字のみ取り出す&lt;br /&gt;
*fnc.className でフォントを適用できる&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import { Inconsolata } from 'next/font/google';&lt;br /&gt;
const fnt = Inconsolata({ subsets: ['latin'] });&lt;br /&gt;
&lt;br /&gt;
  :&lt;br /&gt;
&amp;amp;lt;body className={`${fnt.className}` }&amp;amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==MUI==&lt;br /&gt;
[[MUI]]&lt;/div&gt;</summary>
		<author><name>Piroto</name></author>
		
	</entry>
	<entry>
		<id>https://www.typea.info/tips_/index.php?title=Next.js&amp;diff=35323</id>
		<title>Next.js</title>
		<link rel="alternate" type="text/html" href="https://www.typea.info/tips_/index.php?title=Next.js&amp;diff=35323"/>
		<updated>2024-10-05T05:37:49Z</updated>

		<summary type="html">&lt;p&gt;Piroto: /* Tailwind CSS */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[React]] | [[MUI]] |&lt;br /&gt;
&lt;br /&gt;
{{amazon|4815619484}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Reactは、あくまでUI部分のみ&lt;br /&gt;
*本格的なアプリ開発には周辺領域を担うためのフレームワークが必要&lt;br /&gt;
*Reactベースのフレームワークとしてデファクトスタンダードと言える存在&lt;br /&gt;
*主なライブラリ&lt;br /&gt;
**ファイルシステムベースの設定レスルーター&lt;br /&gt;
**サーバーコンポーネント&lt;br /&gt;
**データ取得用fetchメソッド&lt;br /&gt;
**リソース組み込みの自動最適化&lt;br /&gt;
**CSSフレームワーク、Tailwind　CSSへの標準対応&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=導入=&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
newdelhi:Workspaces piroto$ npx create-next-app@latest&lt;br /&gt;
Need to install the following packages:&lt;br /&gt;
create-next-app@14.2.14&lt;br /&gt;
Ok to proceed? (y) y&lt;br /&gt;
&lt;br /&gt;
✔ What is your project named? … first-nextjs-app&lt;br /&gt;
✔ Would you like to use TypeScript? … No / Yes&lt;br /&gt;
✔ Would you like to use ESLint? … No / Yes&lt;br /&gt;
✔ Would you like to use Tailwind CSS? … No / Yes&lt;br /&gt;
✔ Would you like to use `src/` directory? … No / Yes&lt;br /&gt;
✔ Would you like to use App Router? (recommended) … No / Yes&lt;br /&gt;
✔ Would you like to customize the default import alias (@/*)? … No / Yes&lt;br /&gt;
Creating a new Next.js app in /Users/piroto/Workspaces/first-nextjs-app.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==実行==&lt;br /&gt;
===開発===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
npm run dev&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Start_next_js.png | 300px]]&lt;br /&gt;
&lt;br /&gt;
===本番ビルド＋実行===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
npm run build&lt;br /&gt;
npm start&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==App Router==&lt;br /&gt;
*React Routerとは異なる独自のルーターを標準で提供&lt;br /&gt;
*コンポーネントそのものはReactと変わらない&lt;br /&gt;
&lt;br /&gt;
===2種類のルーター===&lt;br /&gt;
&lt;br /&gt;
*Pages Router : 旧来から提供されている&lt;br /&gt;
*App Router : Next.js 13から導入された新しいルーター(推奨)&lt;br /&gt;
&lt;br /&gt;
====App Router====&lt;br /&gt;
*フォルダベースのルーター&lt;br /&gt;
*ルート定義不要、フォルダ階層に準じてリクエストパスとコンポーネント(.jsファイル)との対応関係が決まる&lt;br /&gt;
*page.jsはファイル名も固定でフォルダー構造だけでリクエストパスが決定される&lt;br /&gt;
&lt;br /&gt;
=====アプリ共通の外枠=====&lt;br /&gt;
*layout.js&lt;br /&gt;
*&amp;amp;lt;html&amp;amp;gt;、&amp;amp;lt;body&amp;amp;gt; 要素が存在し、個々のページを埋め込むため chilrenプロパティを引用していることが条件&lt;br /&gt;
&lt;br /&gt;
===ルートパラメータ===&lt;br /&gt;
*[名前] ： 単一パラメータ&lt;br /&gt;
*[...名前] : キャッチオールセグメント&lt;br /&gt;
*&amp;lt;nowiki&amp;gt;[[...名前]]&amp;lt;/nowiki&amp;gt; : 省略可能なキャッチオールセグメント&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ App Routerのルートパラメータ&lt;br /&gt;
|-&lt;br /&gt;
! フォルダ階層 !! 対応リクエスト !! パラメータ&lt;br /&gt;
|-&lt;br /&gt;
| /app/hoge/[id]/page.js || /hoge/001 || { id : '001' }&lt;br /&gt;
|-&lt;br /&gt;
| /app/foo/[...keys]/page.js || /foo/aaa/bbb || { keys: ['aaa', 'bbb'] }&lt;br /&gt;
|-&lt;br /&gt;
| /app/bar/&amp;lt;nowiki&amp;gt;[[...keys]]&amp;lt;/nowiki&amp;gt;/page.js || /bar || {}&lt;br /&gt;
|-&lt;br /&gt;
| 〃 || /bar/aaa/bbb || { keys: ['aaa', 'bbb'] }&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Tailwind CSS==&lt;br /&gt;
*https://tailwindcss.com/&lt;br /&gt;
*ユーティリティファーストをコンセプトに開発されたCSSフレームワーク&lt;br /&gt;
*ユーティリティを組み合わせてデザインを作るので独自のスタイルを作りやすく細かな調整もしやすいメリット&lt;br /&gt;
*標準のサイズ、カラーなどは用意されている&lt;br /&gt;
&lt;br /&gt;
[https://tailwindcsscheatsheet.com/ Cheat Sheet]&lt;br /&gt;
&lt;br /&gt;
*Tailwind　CSSによるスタイルを適用&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import &amp;quot;./globals.css&amp;quot;;&lt;br /&gt;
    :&lt;br /&gt;
&lt;br /&gt;
&amp;amp;lt;ul className=&amp;quot;fle bg-blue-600 mb-4 pl-2&amp;quot;&amp;amp;gt;...&amp;amp;lt;/ul&amp;amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Prisma==&lt;br /&gt;
*JavaScriptアプリからデータベース操作を取り持つO/Rマッパー&lt;br /&gt;
===インストール===&lt;br /&gt;
*成功すると以下のファイルが生成される&lt;br /&gt;
**.env : 環境変数ファイル、gitignore に追加する&lt;br /&gt;
** prisma/schema.prisma : Prismaのスキーマファイル&lt;br /&gt;
&lt;br /&gt;
sqliteでの構成例&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ npm install prisma --save-dev&lt;br /&gt;
 $ npx prisma init --datasource-provider sqlite&lt;br /&gt;
 warn You already have a .gitignore file. Don't forget to add `.env` in it to not commit any private information.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===データモデルの定義===&lt;br /&gt;
*prisma/schema.prisma に追記&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
model　reviews {&lt;br /&gt;
  id          String @id&lt;br /&gt;
  title       String&lt;br /&gt;
  author      String&lt;br /&gt;
  price       Int&lt;br /&gt;
  publlisher  String&lt;br /&gt;
  published   String&lt;br /&gt;
  image       String&lt;br /&gt;
  read        DateTime  @default(now())&lt;br /&gt;
  memo        String&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*DBに反映&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ npx prisma db push&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Prisma Studio(Webベース管理ツール)で確認&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ npx prisma studio&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==サーバーアクション==&lt;br /&gt;
*Next.js内蔵の仕組み&lt;br /&gt;
*ページコンポーネント、イベントハンドラー、&amp;amp;lt;form&amp;amp;lt;要素のaction属性などからサーバーコードを呼び出す仕組み&lt;br /&gt;
*サーバーとのやりとりに際し、fetchなどの非同期通信コードの不要となり、例えばコンポーネントからデータベースを操作するにも直感的なコードを記述できる&lt;br /&gt;
*現時点ではα版&lt;br /&gt;
&lt;br /&gt;
===有効化===&lt;br /&gt;
&lt;br /&gt;
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]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
const nextConfig = {&lt;br /&gt;
    experimental: {&lt;br /&gt;
        serverActions: true&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==実装==&lt;br /&gt;
&lt;br /&gt;
===ルートレイアウト===&lt;br /&gt;
====アプリ内のリンクにはLinkコンポーネントを利用====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import Link from &amp;quot;next/link&amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
規定で以下のようなコンポーネントが用意されており、アプリ内リソースを効率的に利用できる&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ コンポーネント&lt;br /&gt;
|-&lt;br /&gt;
! コンポーネント !! 概要&lt;br /&gt;
|-&lt;br /&gt;
| &amp;amp;lt;Link&amp;amp;gt; || リンクを生成&lt;br /&gt;
|-&lt;br /&gt;
| &amp;amp;lt;Script&amp;amp;gt; || スクリプトのロード&lt;br /&gt;
|-&lt;br /&gt;
| &amp;amp;lt;Image&amp;amp;gt; || 画像を表示&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
====メタデータ====&lt;br /&gt;
*メタデータを定義しておくことで、個々のページに適切なヘッダーなどを埋め込める&lt;br /&gt;
*複数箇所で宣言された場合、シャローマージされる&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
export const metadata: Metadata = {&lt;br /&gt;
  title: &amp;quot;Reading Recorder&amp;quot;,&lt;br /&gt;
  description: &amp;quot;自分が読んだ書籍の記録を残す&amp;quot;,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*generateMetadata関数を利用しデータベースなどから取得した結果を元に動的に生成も可能&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
export async function generateMetadata({ params, searchParams }) {&lt;br /&gt;
    :&lt;br /&gt;
    return {&lt;br /&gt;
        title : result.title,&lt;br /&gt;
            :&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==フォント==&lt;br /&gt;
*Googleフォント(無償フォントのディレクトリサービス)を有効化&lt;br /&gt;
*具体的なフォントはGoogleフォントから自由に選択できるが一般的にはバリアブルフォント推奨(下例ではInconsolata)&lt;br /&gt;
*フォントはファイルサイズが大きいので、subsetで利用する文字のみ取り出す&lt;br /&gt;
*fnc.className でフォントを適用できる&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import { Inconsolata } from 'next/font/google';&lt;br /&gt;
const fnt = Inconsolata({ subsets: ['latin'] });&lt;br /&gt;
&lt;br /&gt;
  :&lt;br /&gt;
&amp;amp;lt;body className={`${fnt.className}` }&amp;amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Piroto</name></author>
		
	</entry>
	<entry>
		<id>https://www.typea.info/tips_/index.php?title=MUI&amp;diff=35322</id>
		<title>MUI</title>
		<link rel="alternate" type="text/html" href="https://www.typea.info/tips_/index.php?title=MUI&amp;diff=35322"/>
		<updated>2024-10-05T05:30:36Z</updated>

		<summary type="html">&lt;p&gt;Piroto: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[React]] | [[Next.js]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*https://mui.com/&lt;br /&gt;
*Material UI (MUI) はReactアプリで利用できるコンポーネントを集めたライブラリ&lt;br /&gt;
&lt;br /&gt;
==主なコンポーネント==&lt;br /&gt;
*MUI Core　： 基本コンポーネント(無償)&lt;br /&gt;
*MUI X :　より複雑なユースケースに対応下コンポーネント群(一部有償)&lt;br /&gt;
*Templates : MUIベースで構築されたテンプレート群&lt;/div&gt;</summary>
		<author><name>Piroto</name></author>
		
	</entry>
</feed>