T
TanStack10mo ago
xenial-black

How to create multiple routes with createFileLazyRoute e.g. / and /page/$page & <Suspense>

My goal is a single component that handles / and /page/$page I tried the following, but when I save it it removes the (page/$page?) from the createLazyFileRoute... I'd prefer to not have to create a separate lazy route if at all possible
import PostCard from "@/components/PostCard";
import { Post } from "@/types/Post";

import { createLazyFileRoute, useParams } from "@tanstack/react-router";
import { useSuspenseQuery } from "@tanstack/react-query";
import Pagination from "@/components/Pagination";
import { Suspense } from "react";
import PostSkeleton from "@/components/PostSkeleton";

export const Route = createLazyFileRoute("/(page/$page?)")({
component: () => (
<Suspense fallback={<PostSkeleton />}>
<Index />
</Suspense>
),
});

function Index() {
const { page = "1" } = useParams({ from: "/page/$page" });
const getPosts = async (page: number) => {
const response = await fetch(
`https://jsonplaceholder.typicode.com/posts?_page=${page}&_limit=9`
);
const posts = await response.json();

return {
posts,
totalPages: response.headers.get("x-total-count"),
};
};

const { data: posts } = useSuspenseQuery<{
posts: Post[];
totalPages: string | null;
}>({
queryKey: ["posts", page],
queryFn: () => getPosts(parseInt(page.toString(), 10)),
});

return (
<>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
{posts.posts.map((post: Post) => (
<PostCard key={post.id} post={post} />
))}
</div>
{posts.totalPages && (
<div className="flex justify-center items-center my-10">
<Pagination
totalPages={parseInt(posts.totalPages)}
currentPage={parseInt(page.toString() || "1")}
/>
</div>
)}
</>
);
}
import PostCard from "@/components/PostCard";
import { Post } from "@/types/Post";

import { createLazyFileRoute, useParams } from "@tanstack/react-router";
import { useSuspenseQuery } from "@tanstack/react-query";
import Pagination from "@/components/Pagination";
import { Suspense } from "react";
import PostSkeleton from "@/components/PostSkeleton";

export const Route = createLazyFileRoute("/(page/$page?)")({
component: () => (
<Suspense fallback={<PostSkeleton />}>
<Index />
</Suspense>
),
});

function Index() {
const { page = "1" } = useParams({ from: "/page/$page" });
const getPosts = async (page: number) => {
const response = await fetch(
`https://jsonplaceholder.typicode.com/posts?_page=${page}&_limit=9`
);
const posts = await response.json();

return {
posts,
totalPages: response.headers.get("x-total-count"),
};
};

const { data: posts } = useSuspenseQuery<{
posts: Post[];
totalPages: string | null;
}>({
queryKey: ["posts", page],
queryFn: () => getPosts(parseInt(page.toString(), 10)),
});

return (
<>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
{posts.posts.map((post: Post) => (
<PostCard key={post.id} post={post} />
))}
</div>
{posts.totalPages && (
<div className="flex justify-center items-center my-10">
<Pagination
totalPages={parseInt(posts.totalPages)}
currentPage={parseInt(page.toString() || "1")}
/>
</div>
)}
</>
);
}
1 Reply
reduced-jade
reduced-jade10mo ago
we don't support optional path segments yet

Did you find this page helpful?