alpaca pwaa
alpaca pwaa

Reputation: 61

Cannot read properties of undefined (reading '_context') using tRPC with getUserFiles in React component

I'm encountering an error "Cannot read properties of undefined (reading '_context')" when using the getUserFiles procedure from my tRPC client within a React component. I should be able to get the correct type for my data but it gives "any". The error occurs on my Dashboard, specifically, on my const { data: files, isLoading } = trpc.getUserFiles.useQuery();

Prisma schema where I define my files

generator client {
  provider = "prisma-client-js"
}

datasource db {
  provider  = "postgresql"
  url       = env("DATABASE_URL")
  directUrl = env("DIRECT_URL")
}

model User {
  id    String @id @unique
  email String @unique

  File File[]

  stripeCustomerId       String?   @unique @map(name: "stripe_customer_id")
  stripeSubscriptionId   String?   @unique @map(name: "stripe_subscription_id")
  stripePriceId          String?   @map(name: "stripe_price_id")
  stripeCurrentPeriodEnd DateTime? @map(name: "stripe_current_period_end")
}

enum UploadStatus {
  PENDING
  PROCESSING
  FAILED
  SUCCESS
}

model File {
  id   String @id @default(cuid())
  name String

  uploadStatus UploadStatus @default(PENDING)
  url          String
  key          String

  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt

  User   User?   @relation(fields: [userId], references: [id])
  userId String?
}

Here's my getUserFiles

import { db } from "@/db";
import { getKindeServerSession } from "@kinde-oss/kinde-auth-nextjs/server";
import { TRPCError } from "@trpc/server";
import { privateProcedure, publicProcedure, router } from "./trpc";

export const appRouter = router({
  authCallback: publicProcedure.query(async () => {
    // Get the user from the KindeServer session
    const { getUser } = getKindeServerSession();
    const user = await getUser();

    // If the user is not authenticated, throw an error
    if (!user || !user.id || !user.email)
      throw new TRPCError({ code: "UNAUTHORIZED" });

    // check if the user is in the database
    const dbUser = await db.user.findFirst({
      where: {
        id: user.id,
      },
    });

    if (!dbUser) {
      // create user in db
      await db.user.create({
        data: {
          id: user.id,
          email: user.email,
        },
      });
    }

    // Check if user exists in the database
    return { success: true };
  }),

  // Get user files from the database
  getUserFiles: privateProcedure.query(async ({ ctx }) => {
    // Extract the user ID from the context
    const { userId } = ctx;

    // Query the database for files belonging to the user
    return await db.file.findMany({
      where: {
        userId,
      },
    });
  }),
});

export type AppRouter = typeof appRouter;

Here's my private procedure

import { getKindeServerSession } from "@kinde-oss/kinde-auth-nextjs/server";
import { TRPCError, initTRPC } from "@trpc/server";

const t = initTRPC.create();
const middleware = t.middleware;

const isAuth = middleware(async (opts) => {
  const { getUser } = getKindeServerSession();
  const user = await getUser();

  if (!user || !user.id) {
    throw new TRPCError({ code: "UNAUTHORIZED" });
  }

  return opts.next({
    ctx: {
      userId: user.id,
      user,
    },
  });
});

export const router = t.router;
export const publicProcedure = t.procedure;
export const privateProcedure = t.procedure.use(isAuth);

Here's where the error occurs

import { trpc } from "@/app/_trpc/client";
import UploadButton from "./UploadButton";
import { Ghost } from "lucide-react";

const Dashboard = () => {
  const { data: files, isLoading } = trpc.getUserFiles.useQuery();

  return (
    <main className="mx-auto max-w-7xl md:p-10">
      <div className="mt-8 flex flex-col items-start justify-between gap-4 border-b border-gray-200 pb-5 sm:flex-row sm:items-center sm:gap-0">
        <h1 className="mb-3 font-bold text-5xl text-gray-900">My Files</h1>

        <UploadButton />
      </div>

      {/* Display All User Files */}
      {files && files?.length !== 0 ? (
        <div></div>
      ) : isLoading ? (
        <div></div>
      ) : (
        <div className="mt-16 flex flex-col items-center gap-2">
          <Ghost className="h-8 text-zinc-800" />
          <h3 className="font-semibold text-xl">
            Let&apos;s upload your first PDF.
          </h3>
        </div>
      )}
    </main>
  );
};

export default Dashboard;

Upvotes: 3

Views: 951

Answers (1)

Bilal Shaikh
Bilal Shaikh

Reputation: 21

Making the nextJS component, a client component worked for me. You can do that by adding

"use client";

at the top of your file.

Upvotes: 2

Related Questions