ค้นหาเว็บไซต์

reactjs - การแยกคำสั่ง Prisma ที่ซับซ้อนในแอป Next.js


ฉันมีแอป Next.JS ฉันต้องการเรนเดอร์ฟีดรายการงานในหน้าแรก แต่ก็ต้องการในหน้าผู้ใช้ด้วย ฉันติดขัดเล็กน้อยเกี่ยวกับวิธีการแยกคำสั่ง Prisma ของฉัน

ฉันดึงวัตถุข้อมูลขนาดใหญ่โดยใช้ getServerSideProps และส่งสิ่งนี้ไปยังคอมโพเนนต์หน้า (และใช้ react-query เพื่อทำการ hydrate และดึงข้อมูลซ้ำ แต่ตอนนี้ไม่เกี่ยวข้อง) - getRecentTodos (รวมถึง todos) สำหรับหน้าแรกของฉัน - getUserDetailsByName (รวมถึง todos) สำหรับหน้าผู้ใช้

export type getRecentTodos = ReturnType<typeof getRecentTodos> extends Promise<
  infer T
>
  ? T
  : never
export const getRecentTodos = async (recentItemsAmount = 20) => {
  return await prisma.todos.findMany({
    where: { done: true },
    select: {
      id: true,
      userId: true,
      content: true,
      done: true,
      createdAt: true,
      attachments: true,
      todoReplies: {
        select: {
          id: true,
          userId: true,
          content: true,
          todoReplyLikes: true,
          todoId: true,
          user: { select: { name: true, displayName: true, image: true } },
        },
        orderBy: { createdAt: 'asc' },
      },
      todoLikes: {
        select: {
          user: true,
        },
      },
      user: {
        select: {
          name: true,
          displayName: true,
          image: true,
        },
      },
    },
    orderBy: { createdAt: 'desc' },
    take: recentItemsAmount,
  })
}
export const getUserDetailsByName = async (username: string) => {
  return await prisma.user.findUnique({
    where: {
      name: username,
    },
    select: {
      name: true,
      displayName: true,
      bio: true,
      location: true,
      twitter: true,
      image: true,
      createdAt: true,
      todos: {
        select: {
          id: true,
          content: true,
          userId: true,
          done: true,
          updatedAt: true,
          createdAt: true,
          attachments: true,
          user: true,
          todoLikes: true,
          todoReplies: {
            take: 30,
            orderBy: { createdAt: 'desc' },
            select: {
              id: true,
              userId: true,
              todoId: true,
              createdAt: true,
              content: true,
              user: true,
            },
          },
        },
        take: 30,
        orderBy: { createdAt: 'desc' },
      },
      projects: true,
    },
  })
}

ทั้งสองคำสั่งค้นหาจะส่งคืน ‘todos’ แต่สามารถส่งคืนในรูปแบบที่แตกต่างกันเล็กน้อย ส่วนประกอบฟีด todo คาดหวังให้มีคุณสมบัติบางอย่างพร้อมใช้งาน - เช่น displayName บน todoReplies - แต่ในการเรียก getUserDetailsByName displayName อาจไม่ใช่ส่วนหนึ่งของการตอบสนองหรือฝังอยู่ลึกลงไปอีกหนึ่งชั้นหรือบางอย่าง

  • จะทำอย่างไรไม่ให้เรื่องนี้ซับซ้อนเร็วเกินไป?

    • คุณอยากเลือกงานที่ต้องทำในคำค้นหาในลักษณะเดียวกันมากหรือน้อย (ส่งกลับสิ่งเดียวกันและละเว้นสิ่งเดียวกัน ยกเว้นบางอย่างเช่นลำดับ)
    • แต่การคอยปรับสิ่งเหล่านี้ให้ตรงกันด้วยมือในหลาย ๆ คำถามจะซับซ้อนอย่างรวดเร็ว

วิธีแก้ไขที่เป็นไปได้?

  • ฉันควรแยก getServerSideProps ออกเป็นหลายการดึงข้อมูลหรือไม่?

    • ดังนั้น แทนที่จะใช้ ‘getUserDetailsByName’ หนึ่งตัว ซึ่งมี todos อยู่ในรูปแบบฟิลด์ความสัมพันธ์

      • ดึงรายละเอียดผู้ใช้
      • ดังนั้นแทนที่จะใช้ ‘getUserDetailsByName’ หนึ่งตัวซึ่งมี todos เป็นฟิลด์ความสัมพันธ์รวมอยู่
      • ดึงรายละเอียดผู้ใช้

      • ดึงงานที่ต้องทำ
    • นี่หมายความว่าฉันก็ต้องเขียนโค้ด react-query เพิ่มสำหรับการดึงข้อมูลใหม่ ฯลฯ… เพราะคุณกำลังจัดการกับหลายอ็อบเจ็กต์ แต่ก็ทำให้แยกความรับผิดชอบได้ชัดเจนขึ้น
  • การใช้ Typescript เพื่อจับมันในฐานรหัสของฉันเมื่อฟังก์ชันพยายามเข้าถึงคุณสมบัติที่ไม่ได้ถูกส่งกลับจากการค้นหา Prisma เฉพาะนั้นหรือไม่? (ฉันเพิ่งเริ่มเห็นความเป็นไปได้ของ Typescript สำหรับสิ่งแบบนี้)

  • ฉันควรจะทำให้การสร้างงานใน Prisma query เป็นมาตรฐานด้วยฟังก์ชันแล้วรวมฟังก์ชันนั้นไว้ภายใน Prisma queries หรือไม่? คุณสามารถรวมเช่น:

const todoSelect = {
  id: true,
  userId: true,
  content: true,
  {.......}
  user: {
    select: {
      name: true,
      displayName: true,
      image: true,
    },
  },
}

export type getRecentTodos = ReturnType<typeof getRecentTodos> extends Promise<
  infer T
>
  ? T
  : never
export const getRecentTodos = async (recentItemsAmount = 20) => {
  return await prisma.todos.findMany({
    where: { done: true },
    select: todoSelect,
    orderBy: { createdAt: 'desc' },
    take: recentItemsAmount,
  })
}

const userSelect = {
  name: true,
    {......}
  todos: {
    select: todoSelect,
    take: 30,
    orderBy: { createdAt: 'desc' },
  },
  projects: true,
}

export const getUserDetailsByName = async (username: string) => {
  return await prisma.user.findUnique({
    where: {
      name: username,
    },
    select: userSelect,
  })
}