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

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

Barbara Streisand
リリース: 2025-01-20 06:09:09
オリジナル
799 人が閲覧しました

私は 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 サイトの他の関連記事を参照してください。

ソース:dev.to
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
著者別の最新記事
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート