เราจะสร้างส่วนความคิดเห็นสำหรับบล็อกของคุณในบทช่วยสอนนี้ กลุ่มเทคโนโลยีที่เราจะเป็น:
- NextJS 13 (ใน App dir)
- NextAuth (สำหรับการตรวจสอบสิทธิ์)
- Upstash Redis (สำหรับจัดเก็บความคิดเห็น)
- SWR (สำหรับการแคชและการตรวจสอบความคิดเห็นอีกครั้ง)
เริ่มกันเลย
การจัดการการรับรองความถูกต้องด้วย NextAuth
ประการแรกเราไม่สามารถปล่อยให้ใครแสดงความคิดเห็นได้ใช่ไหม? บางคนสามารถเรียกใช้สคริปต์เพื่อสแปมบล็อกของคุณด้วยความคิดเห็นได้ ขั้นแรกเรามาสร้างระบบการรับรองความถูกต้องก่อนที่จะให้ผู้อื่นแสดงความคิดเห็น เราจะใช้ NextAuth
ติดตั้ง 04 ในโครงการของคุณ
pnpm install next-auth นี่คือโครงสร้างไดเรกทอรีภายใน App Directory
.
├── app
│ ├── api
│ │ └── auth
│ │ └── [...nextauth]
│ │ └── route.ts
│ ├── blog
│ │ ├── page.tsx
│ │ └── [...slug]
│ │ └── page.tsx
│ ├── components
│ │ └── LoginButton.tsx
│ ├── favicon.ico
│ ├── globals.css
│ ├── layout.tsx
ตั้งค่าเส้นทาง Auth API ของเรา:
// app/api/auth/[...nextauth]/route.ts
import NextAuth from "next-auth";
import GithubProvider from "next-auth/providers/github";
const handler = NextAuth({
providers: [
GithubProvider({
clientId: process.env.GITHUB_CLIENT_ID!,
clientSecret: process.env.GITHUB_CLIENT_SECRET!,
}),
],
callbacks: {
async session({ session, token }) {
if (session && session.user && token.sub) {
session.user.sub = token.sub;
}
return session;
},
},
});
export { handler as GET, handler as POST };
สร้างแอปพลิเคชัน Github OAuth ใหม่จากที่นี่เพื่อรับ 11 และ 26รหัส> .

ตอนนี้ NextAuth ช่วยให้คุณสามารถลงชื่อเข้าใช้และออกจากระบบจากส่วนประกอบไคลเอ็นต์ใดๆ โดยใช้ 31 และ 43รหัส> ฟังก์ชั่นจาก 56 . แต่ก่อนหน้านั้น คุณต้องตั้งค่า Context Provider ซึ่งจะรวมแอปพลิเคชันทั้งหมดของคุณไว้
// app/layout.tsx
"use client";
import "./globals.css";
import { SessionProvider } from "next-auth/react";
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="en">
<SessionProvider>
<body>{children}</body>
</SessionProvider>
</html>
);
}
62รหัส> จะช่วยให้คุณสามารถเข้าถึงสถานะเซสชันจากส่วนประกอบไคลเอนต์ใด ๆ ในแอปพลิเคชัน
คุณสามารถเข้าถึงสถานะเซสชันได้โดยใช้ 76 ขอจาก 83 . นี่คือตัวอย่างสำหรับปุ่มเข้าสู่ระบบ:
"use Client";
import { signIn, signOut, useSession } from "next-auth/react";
export default function LoginButton() {
const { data: session } = useSession();
if (session) {
return (
<div>
Signed in as {session.user?.name} using {session.user?.email} <br />
<button onClick={() => signOut()}>Sign out</button>
</div>
);
}
return (
<div>
Not signed in <br />
<button onClick={() => signIn()}> Sign in </button>
</div>
);
} ด้วยเหตุนี้ ระบบการตรวจสอบสิทธิ์ของเราจึงพร้อมใช้งาน ตอนนี้เรามาเริ่มเส้นทางฝั่งเซิร์ฟเวอร์เพื่อจัดเก็บความคิดเห็นในฐานข้อมูล Redis กันดีกว่า
การตั้งค่าฐานข้อมูล Redis
- ไปที่ Upstash และสร้างฐานข้อมูล Redis
- เลือกภูมิภาคที่ใกล้กับผู้ใช้ของคุณและเลือกการเข้ารหัส TLS
- ติดตั้ง
94แพ็คเกจ
pnpm install @upstash/redis

- คัดลอกโทเค็นเหล่านี้ใน
109ของคุณ .
มาเขียนจุดสิ้นสุด API ของเราในโครงสร้างไดเร็กทอรีนี้:
.
├── app
│ ├── api
│ │ ├── auth
│ │ │ └── [...nextauth]
│ │ │ └── route.ts
│ │ ├── comment
│ │ │ ├── delete
│ │ │ │ └── route.ts
│ │ │ ├── get
│ │ │ │ └── route.ts
│ │ │ └── post
│ │ │ └── route.ts
│ │ └── lib
│ │ ├── getUser.ts
│ │ └── redis.ts
- สร้างอินสแตนซ์ไคลเอ็นต์ Redis
// app/api/lib/redis.ts
import { Redis } from "@upstash/redis";
/*
This tries to load UPSTASH_REDIS_REST_URL
and UPSTASH_REDIS_REST_TOKEN from your environment
using process.env
*/
const redis = Redis.fromEnv();
export default redis; นั่นก็คือมัน ขณะนี้ไคลเอนต์ Redis ของเราได้รับการตั้งค่าแล้ว และสิ่งที่เหลืออยู่คือการตั้งค่า APIroutes ในแอปพลิเคชันของเรา
เราจะใช้รายการ Redis เพื่อจัดเก็บความคิดเห็น พวกเขาสามารถทำหน้าที่เป็นสแต็กเพื่อให้ความคิดเห็นล่าสุดปรากฏที่ด้านบน แน่นอนว่าเรายังใช้ตรรกะการเรียงลำดับฝั่งไคลเอ็นต์ได้ แต่เมื่อ Redis มีโครงสร้างข้อมูลนี้อยู่แล้ว ก็ลองใช้เลย
คุณสามารถดูรหัสทั้งหมดได้ที่นี่ นี่คือส่วนสำคัญของมัน:
-
สร้างความคิดเห็น:
116. สิ่งนี้จะผลักดันความคิดเห็นในรายการที่มีคีย์126ป> -
รับความคิดเห็นทั้งหมด
135ป> -
ลบความคิดเห็น
148. การดำเนินการนี้จะลบรายการ158ทั้งหมด ในรายการด้วยคีย์162.
API ของเราพร้อมใช้งานแล้ว มาเริ่มบูรณาการส่วนหน้ากับส่วนหลังกันดีกว่า
การตั้งค่าฝั่งไคลเอ็นต์
มันไม่ใช่เรื่องยากเลย เราเพียงแค่ต้องเข้าถึงจุดสิ้นสุดที่เราเพิ่งสร้างขึ้นโดยใช้ 176 เราจะใช้ไลบรารีชื่อ 181 สำหรับการแคชและการตรวจสอบความคิดเห็นอีกครั้ง แต่อย่าลังเลที่จะใช้ไลบรารีอื่นเช่น React Query เพื่อมัน
เราสร้าง 192 hook ซึ่งจะมี 201 และ 214รหัส> ตัวจัดการสำหรับการร้องขอ
"use client";
import { useState } from "react";
import type { Comment } from "@/app/interfaces/interfaces";
import useSWR from "swr";
const fetcher = (url: string) => fetch(url).then((res) => res.json());
const useComment = () => {
const [text, setText] = useState("");
const { data: comments, mutate } = useSWR<Comment[]>(
"/api/comment/get",
fetcher,
{
fallbackData: [],
},
);
const onSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
try {
await fetch("/api/comment/post", {
method: "POST",
body: JSON.stringify({ text }),
headers: {
"Content-Type": "application/json",
},
});
setText("");
await mutate();
} catch (error) {
console.log(error);
}
};
const onDelete = async (comment: Comment) => {
try {
await fetch("/api/comment/delete", {
method: "POST",
body: JSON.stringify({ comment }),
headers: {
"Content-Type": "application/json",
},
});
await mutate();
} catch (error) {
console.log(error);
}
};
return { text, setText, comments, onSubmit, onDelete };
};
export default useComment; ตอนนี้ส่วนความคิดเห็นของเราเสร็จสิ้นแล้ว เราสามารถดึงข้อมูล โพสต์ และลบความคิดเห็นได้ ขั้นตอนต่อไปคือการสร้างส่วนประกอบสำหรับกล่องความคิดเห็นและรายการความคิดเห็น นี่คือตัวอย่างที่สมบูรณ์