首页 >web前端 >css教程 >使用 Supabase 构建生产级 Web 应用程序 – 第 2 部分

使用 Supabase 构建生产级 Web 应用程序 – 第 2 部分

Barbara Streisand
Barbara Streisand原创
2025-01-20 06:09:09800浏览

我正在阅读 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中文网其他相关文章!

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn