検索
ホームページウェブフロントエンドCSSチュートリアルSupabase を使用した本番グレードの Web アプリケーションの構築 – パート 2

私は David Lorenz の著書『Building Production-Grade Web Applications with Supabase』 (アフィリエイトリンク) に取り組んでおり、第 3 章 – チケット管理ページの作成…を終えたところです。いくつか問題が発生したので、その解決方法とともに共有したいと思います。

セクション: Next.js を使用した Pico.css のセットアップ

pageProps.children は無視して、子のままにすることができます。

セクション: ログインフォームの構築

本当に app/page.js を LoginPage として編集する必要がありますかSupabase を使用した本番グレードの Web アプリケーションの構築 – パート 2

ローレンツは次のように明確に述べていますが、

それでは、app/page.js を開き、Page コンポーネントを変更して、今のところ Login コンポーネントのみを返すようにします…

次に LoginPage を編集する指示に遭遇したときも、自分で探さなければなりませんでした。既存の page.js を使用するのではなく、新しいページを作成することを期待していましたが、そうではありません。page.js 内のすべてを消去し、本に記載されているように LoginPage コードのみを貼り付けます。

エラー: searchParams は待機する必要があります

app/Login.js を切り替えロジック (パスワード フィールドのオン/オフを切り替えるため) で更新すると、次のエラーが表示され始めます。

Error: Route "/" used `searchParams.magicLink`. `searchParams` should be awaited before using its properties. Learn more: https://nextjs.org/docs/messages/sync-dynamic-apis
    at LoginPage (src/app/page.js:3:38)
  1 | import { Login } from "./Login";
  2 | export default function LoginPage({ searchParams }) {
> 3 | const wantsMagicLink = searchParams.magicLink === "yes";
    | ^
  4 | return <login ispasswordlogin="{!wantsMagicLink}"></login>;
  5 | }

これを修正するには、app/page.js の LoginPage 関数を次のように非同期にします。

import { Login } from "./Login";

export default async function LoginPage({ searchParams }) {
  const params = await searchParams;
  const wantsMagicLink = params.magicLink === "yes";
  return <login ispasswordlogin="{!wantsMagicLink}"></login>;
}

ユーザー名とパスワードの保存

この本では、Login.js のコードを次のように更新するように指示されています。

"use client";
import { useRef } from "react";
export const Login = () => {
const emailInputRef = useRef(null);
const passwordInputRef = useRef(null);
return (
...
)
}

これが完全に明確ではない場合に備えて、コードは次のようになります。

"use client";
import { useRef } from "react";
import Link from "next/link";

export const Login = ({ isPasswordLogin }) => {
  const emailInputRef = useRef(null);
  const passwordInputRef = useRef(null);

  return(
    ...
  )
}

どこに... 何も変更していません。基本的に、 return( on からのすべては以前とまったく同じままです。

私が上で指摘している「重要なこと」は、「next/link」から import Link を削除すべきではないということです。代わりに「クライアントを使用」を追加します。そしてその前に useRef import があります。

補足: 後で学ぶことになるかもしれませんが、ここで useState の代わりに useRef を使用するのは少し奇妙に感じますが、繰り返しになりますが、私は Next.js や React の専門家ではありません。

onSubmit イベントはどこに行くのでしょうかSupabase を使用した本番グレードの Web アプリケーションの構築 – パート 2

Login.js の return( ... ) 内で、現在の

を置き換えます。 onSubmit ハンドラーを含むフォーム コードを使用します。

セクション: チケット管理 UI の視覚化

サブセクション: ナビゲーション要素を含む共有 UI レイアウトの作成

CSS の元ユニットSupabase を使用した本番グレードの Web アプリケーションの構築 – パート 2

app/tickets/TenantName.js のコードでは、Lorenz はめったに使用されない CSS ex ユニットを使用しています。

<strong>

</strong>

I suspect that this is actually a typo and that Lorenz intended for this to be 1em. While ex is a valid CSS unit it is rarely utilized and is based on the height of the current font. For more on this topic see:

  • W3’s Example Page for EM, PX, PT, CM, IN…
  • W3School’s CSS Units.
  • Perplexity: Should one use the ex CSS unitSupabase を使用した本番グレードの Web アプリケーションの構築 – パート 2

Subsection: Designing the Ticket List Page

Creating dummy tickets whereSupabase を使用した本番グレードの Web アプリケーションの構築 – パート 2

For those who aren’t familiar with React the instruction to add dummyTickets to the page.js file may not be clear enough. You’ll want put these in the TicketListPage() function before the return.

Import howSupabase を使用した本番グレードの Web アプリケーションの構築 – パート 2

Lorenz instructs us to import the TicketList component into page.js. This is pretty straightforward but may be helpful to note that since this is a “named export” we want our import in page.js to look like:

import { TicketList } from "./TicketList";

次のようなものはありません:

import TicketList from "./TicketList";

後者を実行すると、次のような愛らしいエラー メッセージが表示されます。

Error: Route "/" used `searchParams.magicLink`. `searchParams` should be awaited before using its properties. Learn more: https://nextjs.org/docs/messages/sync-dynamic-apis
    at LoginPage (src/app/page.js:3:38)
  1 | import { Login } from "./Login";
  2 | export default function LoginPage({ searchParams }) {
> 3 | const wantsMagicLink = searchParams.magicLink === "yes";
    | ^
  4 | return <login ispasswordlogin="{!wantsMagicLink}"></login>;
  5 | }

サブセクション: チケット詳細ページの構築

エラー: ルート「/tickets/details/[id]」が使用されています…

TicketDetailsPage 関数を作成する手順に従うと、次のエラーが表示されます:

import { Login } from "./Login";

export default async function LoginPage({ searchParams }) {
  const params = await searchParams;
  const wantsMagicLink = params.magicLink === "yes";
  return <login ispasswordlogin="{!wantsMagicLink}"></login>;
}

以前に LoginPage 関数で同様のエラーが発生し、関数を非同期にしてパラメーターを待つことで解決したことを思い出してください。ここでも同じことを行います:

"use client";
import { useRef } from "react";
export const Login = () => {
const emailInputRef = useRef(null);
const passwordInputRef = useRef(null);
return (
...
)
}

エラー: ルート「/tickets/details/[id]」が使用されました… (またSupabase を使用した本番グレードの Web アプリケーションの構築 – パート 2)

/tickets/details/[id]/page.js ファイル (TicketDetailsPage 関数) を更新すると、前のセクションで発生したのと非常によく似たエラーが発生します。何が与えますか?単純に、前のセクションでコードを更新しましたが、ブックはそれを認識しないため、ブックはまだ params.id を使用しています。params.id を id に置き換えるだけで、すべてが雨のように正しくなるはずです。

サブセクション: チケット詳細へのコメントセクションの追加

新しいコメント ファイルのパスは、/tickets/details[id]/TicketComments.js ではなく、/tickets/details/[id]/TicketComments.js である必要があります。

エラー: 同じキーを持つ 2 つの子が見つかりました…

実際のコメントを表示するコードを TicketComments.js に追加した後、Next.js はターミナル出力にエラーをスローしませんが、ブラウザにはエラーが表示されます。

"use client";
import { useRef } from "react";
import Link from "next/link";

export const Login = ({ isPasswordLogin }) => {
  const emailInputRef = useRef(null);
  const passwordInputRef = useRef(null);

  return(
    ...
  )
}

これが発生する理由は 2 つあります。 1 つ目は、文字列リテラル comment.date を渡す {comment.date} を引用符で囲んでいるため、実際には日付をキーとして使用していないことです。これを修正するには、次のように引用符を削除する必要があります:





I suspect that this is actually a typo and that Lorenz intended for this to be 1em. While ex is a valid CSS unit it is rarely utilized and is based on the height of the current font. For more on this topic see:

  • W3’s Example Page for EM, PX, PT, CM, IN…
  • W3School’s CSS Units.
  • Perplexity: Should one use the ex CSS unitSupabase を使用した本番グレードの Web アプリケーションの構築 – パート 2

Subsection: Designing the Ticket List Page

Creating dummy tickets whereSupabase を使用した本番グレードの Web アプリケーションの構築 – パート 2

For those who aren’t familiar with React the instruction to add dummyTickets to the page.js file may not be clear enough. You’ll want put these in the TicketListPage() function before the return.

Import howSupabase を使用した本番グレードの Web アプリケーションの構築 – パート 2

Lorenz instructs us to import the TicketList component into page.js. This is pretty straightforward but may be helpful to note that since this is a “named export” we want our import in page.js to look like:

import { TicketList } from "./TicketList";

は次のように置き換えられます:

import TicketList from "./TicketList";

これが完了すると、そのエラーは発生しなくなりますが、現時点では明らかではないとしても、別の問題があることに注意してください。 2 人以上の人が同じ日にコメントした場合はどうなりますかSupabase を使用した本番グレードの Web アプリケーションの構築 – パート 2ここでもキーが一意ではないため、同じエラーが表示されます。コメントに id プロパティを追加することで、この問題をすぐに修正できます。更新されたコメントは次のようになります:

./src/app/tickets/page.js:1:1 Export default doesn't exist in target module

1 | import TicketList from "./TicketList"; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 
2 | 
3 | export default function TicketListPage() { 4 | const dummyTickets = [

The export default was not found in module [project]/src/app/tickets/TicketList.js [app-rsc] (ecmascript). Did you mean to import TicketListSupabase を使用した本番グレードの Web アプリケーションの構築 – パート 2 All exports of the module are statically known (It doesn't have dynamic exports). So it's known statically that the requested export doesn't exist.

次に変更する必要があるのは次のとおりです。

Error: Route "/tickets/details/[id]" used `params.id`. `params` should be awaited before using its properties. Learn more: https://nextjs.org/docs/messages/sync-dynamic-apis
    at TicketDetailsPage (src/app/tickets/details/[id]/page.js:4:50)
  2 | return (
  3 | <div>
> 4 | Ticket Details page with <strong>ID={params.id}</strong>
    | ^
  5 | </div>
  6 | );
  7 | }

宛先:

export default async function TicketDetailsPage({ params }) {
  const ticketParams = await params;
  const id = ticketParams.id;

  return (
    <div>
      Ticket Details page with <strong>ID={id}</strong>
    </div>
  );
}

サブセクション: 新しいチケットを作成するページの実装

ここには何も見るべきものはありません。

サブセクション: ユーザー概要の実装

アイコンのインストール

@tabler/icons-react パッケージをインストールする必要があります: npm i @tabler/icons-react

Lorenz は IconCheck を使用していますが、表示されている内容がもう少し明確になるため、IconUserCheck を使用することをお勧めします。

users/page.js に IconUserCheck コンポーネントと IconUserOff コンポーネントをインポートする必要があります。

Encountered two children with the same key, `{comment.date}`. Keys should be unique so that components maintain their identity across updates. Non-unique keys may cause children to be duplicated and/or omitted — the behavior is unsupported and could change in a future version.

そして次のものを置き換える必要があります:

<article key="{comment.date}">
</article>

付き:

Error: Route "/" used `searchParams.magicLink`. `searchParams` should be awaited before using its properties. Learn more: https://nextjs.org/docs/messages/sync-dynamic-apis
    at LoginPage (src/app/page.js:3:38)
  1 | import { Login } from "./Login";
  2 | export default function LoginPage({ searchParams }) {
> 3 | const wantsMagicLink = searchParams.magicLink === "yes";
    | ^
  4 | return <login ispasswordlogin="{!wantsMagicLink}"></login>;
  5 | }

パス名 === "/tickets" を、リンクが指しているページに変更します。リンクが /tickets/new を指している場合は、パス名セクションを pathname === "/tickets/new" に設定する必要があります。

結論

おめでとうございます。あなたはこの投稿に興味を持っている人 #3 です。 Supabase を使用した本番グレードの Web アプリケーションの構築 – パート 2

以上がSupabase を使用した本番グレードの Web アプリケーションの構築 – パート 2の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
CSSグリッドとは何ですか?CSSグリッドとは何ですか?Apr 30, 2025 pm 03:21 PM

CSSグリッドは、複雑で応答性の高いWebレイアウトを作成するための強力なツールです。設計を簡素化し、アクセシビリティを向上させ、古い方法よりも多くの制御を提供します。

CSS Flexboxとは何ですか?CSS Flexboxとは何ですか?Apr 30, 2025 pm 03:20 PM

記事では、レスポンシブデザインにおけるスペースの効率的なアラインメントと分布のためのレイアウト方法であるCSS FlexBoxについて説明します。 FlexBoxの使用量を説明し、CSSグリッドと比較し、ブラウザのサポートを詳細に説明します。

CSSを使用してWebサイトを応答するにはどうすればよいですか?CSSを使用してWebサイトを応答するにはどうすればよいですか?Apr 30, 2025 pm 03:19 PM

この記事では、ビューポートメタタグ、柔軟なグリッド、流体メディア、メディアクエリ、相対ユニットなど、CSSを使用してレスポンシブWebサイトを作成するための手法について説明します。また、CSSグリッドとフレックスボックスを使用してカバーし、CSSフレームワークを推奨しています

CSSボックスサイズのプロパティは何をしますか?CSSボックスサイズのプロパティは何をしますか?Apr 30, 2025 pm 03:18 PM

この記事では、要素の寸法の計算方法を制御するCSSボックスサイズのプロパティについて説明します。コンテンツボックス、ボーダーボックス、パディングボックスなどの値と、レイアウト設計とフォームアライメントへの影響について説明します。

CSSを使用してアニメーション化するにはどうすればよいですか?CSSを使用してアニメーション化するにはどうすればよいですか?Apr 30, 2025 pm 03:17 PM

記事では、CSS、キープロパティ、およびJavaScriptとの組み合わせを使用してアニメーションの作成について説明します。主な問題は、ブラウザの互換性です。

CSSを使用してプロジェクトに3D変換を追加できますか?CSSを使用してプロジェクトに3D変換を追加できますか?Apr 30, 2025 pm 03:16 PM

記事では、3D変換、主要なプロパティ、ブラウザの互換性、およびWebプロジェクトのパフォーマンスに関する考慮事項にCSSを使用して説明します。

CSSに勾配を追加するにはどうすればよいですか?CSSに勾配を追加するにはどうすればよいですか?Apr 30, 2025 pm 03:15 PM

この記事では、CSSグラデーション(線形、放射状、繰り返し)を使用して、ウェブサイトのビジュアルを強化し、深さ、フォーカス、および現代の美学を追加します。

CSSの擬似要素とは何ですか?CSSの擬似要素とは何ですか?Apr 30, 2025 pm 03:14 PM

記事では、CSSの擬似要素、HTMLスタイリングの強化における使用、および擬似クラスとの違いについて説明します。実用的な例を提供します。

See all articles

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

Video Face Swap

Video Face Swap

完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

ホットツール

SublimeText3 英語版

SublimeText3 英語版

推奨: Win バージョン、コードプロンプトをサポート!

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

SublimeText3 Linux 新バージョン

SublimeText3 Linux 新バージョン

SublimeText3 Linux 最新バージョン

ZendStudio 13.5.1 Mac

ZendStudio 13.5.1 Mac

強力な PHP 統合開発環境