> 웹 프론트엔드 > CSS 튜토리얼 > Supabase를 사용하여 프로덕션급 웹 애플리케이션 구축 – 2부

Supabase를 사용하여 프로덕션급 웹 애플리케이션 구축 – 2부

Barbara Streisand
풀어 주다: 2025-01-20 06:09:09
원래의
809명이 탐색했습니다.

저는 David Lorenz의 저서 Building Production-Grade Web Application with Supabase(제휴 링크)를 읽고 작업 중이며 3장 – 티켓 관리 페이지 만들기…를 방금 마쳤습니다. 몇 가지 문제가 발생하여 이를 해결한 방법과 함께 공유하고 싶습니다.

섹션: Next.js로 Pico.css 설정

pageProps.children을 무시하고 하위 항목으로 남겨둘 수 있습니다.

섹션: 로그인 양식 작성

정말로 app/page.js를 LoginPage로 편집해야 합니까Supabase를 사용하여 프로덕션급 웹 애플리케이션 구축 – 2부

Lorenz는 다음과 같이 명시적으로 말합니다.

그러므로 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"에서 가져오기 링크를 제거하면 안 된다는 것입니다. 대신 "클라이언트 사용"을 추가하세요. 그리고 그 전에 useRef 가져오기를 수행합니다.

참고: 나중에 배우게 될 수도 있지만 여기에서는 useState 대신 useRef를 사용하는 것이 조금 이상하다고 생각합니다. 하지만 다시 말씀드리지만 저는 Next.js 또는 React 전문가가 아닙니다.

onSubmit 이벤트는 어디로 가나요Supabase를 사용하여 프로덕션급 웹 애플리케이션 구축 – 2부

Login.js에서 return( ... ) 내의 현재

onSubmit 핸들러가 포함된 양식 코드를 사용하세요.

섹션: 티켓 관리 UI 시각화

하위 섹션: 탐색 요소를 사용하여 공유 UI 레이아웃 만들기

CSS ex 유닛Supabase를 사용하여 프로덕션급 웹 애플리케이션 구축 – 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를 사용하여 프로덕션급 웹 애플리케이션 구축 – 2부

Subsection: Designing the Ticket List Page

Creating dummy tickets whereSupabase를 사용하여 프로덕션급 웹 애플리케이션 구축 – 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를 사용하여 프로덕션급 웹 애플리케이션 구축 – 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를 사용하여 프로덕션급 웹 애플리케이션 구축 – 2부)

/tickets/details/[id]/page.js 파일(TicketDetailsPage 함수)을 업데이트한 후 마지막 섹션에서와 매우 유사한 오류가 발생합니다. 무엇을 제공합니까Supabase를 사용하여 프로덕션급 웹 애플리케이션 구축 – 2부 간단합니다. 마지막 섹션에서 코드를 업데이트했지만 책에서는 이를 모르기 때문에 책에서는 여전히 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 unitSupabase를 사용하여 프로덕션급 웹 애플리케이션 구축 – 2부

Subsection: Designing the Ticket List Page

Creating dummy tickets whereSupabase를 사용하여 프로덕션급 웹 애플리케이션 구축 – 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를 사용하여 프로덕션급 웹 애플리케이션 구축 – 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";
로그인 후 복사
로그인 후 복사

이 작업이 완료되면 더 이상 해당 오류가 발생하지 않지만 현재는 명확하지 않더라도 또 다른 문제가 있다는 점에 유의해야 합니다. 두 명 이상의 개인이 같은 날짜에 댓글을 달면 어떻게 되나요Supabase를 사용하여 프로덕션급 웹 애플리케이션 구축 – 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를 사용하여 프로덕션급 웹 애플리케이션 구축 – 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를 사용하여 프로덕션급 웹 애플리케이션 구축 – 2부

위 내용은 Supabase를 사용하여 프로덕션급 웹 애플리케이션 구축 – 2부의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

원천:dev.to
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
저자별 최신 기사
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿