6

TRPC Problem

i have this tweetRouter with a timeline query, which returns tweets and a NextCursor, but when i try to access useInfiniteQuery in my components a error show up.

** Property 'useInfiniteQuery' does not exist on type '{ useQuery: **

Translation: You're trying to access useInfiniteQuery on an object that doesn't contain it.

my component:

export function Timeline() {
  const data = trpc.tweet.timeline.useInfiniteQuery(
    {
      limit: 10,
    },
    {
      getNextPageParam: (lastPage) => lastPage.nextCursor,
    }
  );

  return (
    <Container maxW="xl">
      <CreateTweet />
      <Box
        borderX="1px"
        borderTop="1px"
        borderColor={useColorModeValue("gray.200", "gray.700")}
      >
        {data?.tweets.map((tweet) => {
          return <Tweet key={tweet.id} tweet={tweet} />;
        })}
      </Box>
    </Container>
  );
}

my tweet.ts router:

import { z } from "zod";
import { tweetSchema } from "../../../components/CreateTweet";
import { protectedProcedure, publicProcedure, router } from "../trpc";

export const tweetRouter = router({
  create: protectedProcedure.input(tweetSchema).mutation(({ ctx, input }) => {
    const { prisma, session } = ctx
    const { text } = input

    const userId = session.user.id

    return prisma.tweet.create({
      data: {
        text,
        author: {
          connect: {
            id: userId,
          }
        }
      }
    })
  }),
  timeline: publicProcedure.input(
    z.object({
      cursor: z.string().nullish(),
      limit: z.number().min(1).max(100).default(10)
    })
  ).query(async ({ ctx, input }) => {
    const { prisma } = ctx
    const { cursor, limit } = input

    const tweets = await prisma.tweet.findMany({
      take: limit + 1,
      orderBy: [
        {
          createdAt: "desc"
        }
      ],
      cursor: cursor ? { id: cursor } : undefined,
      include: {
        author: {
          select: {
            name: true,
            image: true,
            id: true
          }
        }
      }
    })

    let nextCursor: typeof cursor | undefined = undefined;

    if (tweets.length > limit) {
      const nextItem = tweets.pop() as typeof tweets[number];

      nextCursor = nextItem!.id;
    }

    return {
      tweets,
      nextCursor,
    };
  })
})

my prisma model:

model Tweet {
  id   String @id @default(cuid())
  text String

  author   User   @relation(fields: [authorId], references: [id])
  authorId String

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

and my autocompletion only shows up useQuery and useSuspenseQuery

i'm expecting to do a infinite scroll using useInfiniteQuery

ricardovac
  • 61
  • 1
  • 4
  • Did you find a solution? I'm having the same issue, using create t3-app default settings. – Tim Feb 13 '23 at 10:08

4 Answers4

2

Try setting compilerOptions.strict to true in your tsconfig.json. That fixed it for me.

Marc
  • 412
  • 4
  • 17
1

I had to change the zod input validation property name from cursorId -> cursor

I also tried your timeline publicProcedure and it works fine on fresh create t3-app install

 getAll: publicProcedure
    .input(
      z.object({
        take: z.number().int(),
     // cursorId: z.string().nullish(),
        cursor: z.string().nullish(),
      }),
    ).query...
Tim
  • 75
  • 1
  • 8
0

Unfortunately, you didn't share your root router in _app.ts

which should look like this

export const appRouter = router({
  tweet: tweetRouter,
});

export type AppRouter = typeof appRouter;

There should not be any problem if you follow this convention and I'm willing to help if you provide more information Because I've worked with useInfiniteQuery() without any issue.

0

Just ran into this same issue using Next.js 13.4.1, TRPC 10.25.1, and Tanstack Query 4.29.5.

The TRPC docs page for useInfiniteQuery says:

"Your procedure needs to accept a cursor input of any type (string, number, etc) to expose this hook."

This dynamic modification of the type doesn't seem to be working correctly.

Setting "compilerOptions": { "strict": true } in your tsconfig.json does work, but comes with a lot of baggage and isn't something I wanted to enable in my codebase.

Instead the simplest solution I found was to arbitrarily redefine the type of the TRPC procedure to 'any', in your case this would look like:

const timelineProcedure: any = trpc.tweet.timeline;
const data = timelineProcedure.useInfiniteQuery(
  {
    limit: 10,
  },
  {
    getNextPageParam: (lastPage) => lastPage.nextCursor,
  }
);
Kurtis
  • 1
  • 2