首頁 > web前端 > css教學 > 使用 Supabase 建立生產級 Web 應用程式 – 第 2 部分

使用 Supabase 建立生產級 Web 應用程式 – 第 2 部分

Barbara Streisand
發布: 2025-01-20 06:09:09
原創
799 人瀏覽過

我正在閱讀 David Lorenz 的書《使用 Supabase 建立生產級 Web 應用程式》(附屬連結),並且剛完成第 3 章 – 建立票證管理頁面...。我遇到了一些問題,我想分享一下這些問題以及我是如何解決這些問題的。

部分:使用 Next.js 設定 Pico.css

您可以忽略 pageProps.children 並將其保留為子項。

部分:建立登入表單

我真的應該將 app/page.js 編輯為 LoginPage 嗎?

儘管洛倫茲明確指出:

因此,開啟 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( 開始的所有內容都與以前完全相同。

我上面指出的“大事”是不應該從“next/link”中刪除 import Link;而是添加“使用客戶端”;以及在其之前的 useRef 導入。

附註:也許我們稍後會學習,但我發現在這裡使用 useRef 而不是 useState 有點奇怪,但話又說回來,我不是 Next.js 或 React 專家。

onSubmit 事件去哪裡了?

在 Login.js 中的 return( ... ) 中,取代目前的

使用包含 onSubmit 處理程序的表單程式碼。

部分:可視化工單管理 UI

小節:使用導航元素建立共享 UI 佈局

CSS前單位?

在 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 unit使用 Supabase 建立生產級 Web 應用程式 – 第 2 部分

Subsection: Designing the Ticket List Page

Creating dummy tickets where使用 Supabase 建立生產級 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 how使用 Supabase 建立生產級 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]”...(再次?)

更新 /tickets/details/[id]/page.js 檔案(TicketDetailsPage 函數)後,我們得到了與上一節非常相似的錯誤。什麼給?很簡單,我們在上一節中更新了程式碼,但書上不知道這一點,所以書上仍然使用 params.id,只需將 params.id 替換為 id ,一切都應該像雨一樣正確。

小節:將評論部分添加到票證詳細資訊中

新評論檔案的路徑應該是 /tickets/details/[id]/TicketComments.js 而不是 /tickets/details[id]/TicketComments.js。

錯誤:遇到兩個孩子擁有同一把鑰匙…

雖然在將顯示實際評論的程式碼新增至 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(
    ...
  )
}
登入後複製
登入後複製

出現這種情況有兩個原因。首先,我們實際上並沒有使用日期作為鍵,因為我們在 {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 unit使用 Supabase 建立生產級 Web 應用程式 – 第 2 部分

Subsection: Designing the Ticket List Page

Creating dummy tickets where使用 Supabase 建立生產級 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 how使用 Supabase 建立生產級 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";
登入後複製
登入後複製

完成此操作後,我們將不再收到該錯誤,但我們應該注意到還有另一個問題,即使目前並不明顯。如果兩個或兩個以上的人在同一日期發表評論會怎麼樣?我們的密鑰又不是唯一的,我們會看到同樣的錯誤。我們可以透過在評論中加入 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 TicketList使用 Supabase 建立生產級 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中文網其他相關文章!

來源:dev.to
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
作者最新文章
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板