Complete to "Client Side Routing"

This commit is contained in:
2025-03-30 21:13:08 +02:00
parent 792bb27d06
commit 3324a15cee
3 changed files with 134 additions and 7 deletions

View File

@@ -12,6 +12,7 @@
import { Route as rootRoute } from './routes/__root' import { Route as rootRoute } from './routes/__root'
import { Route as IndexImport } from './routes/index' import { Route as IndexImport } from './routes/index'
import { Route as ContactsContractIdImport } from './routes/contacts.$contractId'
// Create/Update Routes // Create/Update Routes
@@ -21,6 +22,12 @@ const IndexRoute = IndexImport.update({
getParentRoute: () => rootRoute, getParentRoute: () => rootRoute,
} as any) } as any)
const ContactsContractIdRoute = ContactsContractIdImport.update({
id: '/contacts/$contractId',
path: '/contacts/$contractId',
getParentRoute: () => rootRoute,
} as any)
// Populate the FileRoutesByPath interface // Populate the FileRoutesByPath interface
declare module '@tanstack/react-router' { declare module '@tanstack/react-router' {
@@ -32,6 +39,13 @@ declare module '@tanstack/react-router' {
preLoaderRoute: typeof IndexImport preLoaderRoute: typeof IndexImport
parentRoute: typeof rootRoute parentRoute: typeof rootRoute
} }
'/contacts/$contractId': {
id: '/contacts/$contractId'
path: '/contacts/$contractId'
fullPath: '/contacts/$contractId'
preLoaderRoute: typeof ContactsContractIdImport
parentRoute: typeof rootRoute
}
} }
} }
@@ -39,32 +53,37 @@ declare module '@tanstack/react-router' {
export interface FileRoutesByFullPath { export interface FileRoutesByFullPath {
'/': typeof IndexRoute '/': typeof IndexRoute
'/contacts/$contractId': typeof ContactsContractIdRoute
} }
export interface FileRoutesByTo { export interface FileRoutesByTo {
'/': typeof IndexRoute '/': typeof IndexRoute
'/contacts/$contractId': typeof ContactsContractIdRoute
} }
export interface FileRoutesById { export interface FileRoutesById {
__root__: typeof rootRoute __root__: typeof rootRoute
'/': typeof IndexRoute '/': typeof IndexRoute
'/contacts/$contractId': typeof ContactsContractIdRoute
} }
export interface FileRouteTypes { export interface FileRouteTypes {
fileRoutesByFullPath: FileRoutesByFullPath fileRoutesByFullPath: FileRoutesByFullPath
fullPaths: '/' fullPaths: '/' | '/contacts/$contractId'
fileRoutesByTo: FileRoutesByTo fileRoutesByTo: FileRoutesByTo
to: '/' to: '/' | '/contacts/$contractId'
id: '__root__' | '/' id: '__root__' | '/' | '/contacts/$contractId'
fileRoutesById: FileRoutesById fileRoutesById: FileRoutesById
} }
export interface RootRouteChildren { export interface RootRouteChildren {
IndexRoute: typeof IndexRoute IndexRoute: typeof IndexRoute
ContactsContractIdRoute: typeof ContactsContractIdRoute
} }
const rootRouteChildren: RootRouteChildren = { const rootRouteChildren: RootRouteChildren = {
IndexRoute: IndexRoute, IndexRoute: IndexRoute,
ContactsContractIdRoute: ContactsContractIdRoute,
} }
export const routeTree = rootRoute export const routeTree = rootRoute
@@ -77,11 +96,15 @@ export const routeTree = rootRoute
"__root__": { "__root__": {
"filePath": "__root.tsx", "filePath": "__root.tsx",
"children": [ "children": [
"/" "/",
"/contacts/$contractId"
] ]
}, },
"/": { "/": {
"filePath": "index.tsx" "filePath": "index.tsx"
},
"/contacts/$contractId": {
"filePath": "contacts.$contractId.tsx"
} }
} }
} }

View File

@@ -1,4 +1,4 @@
import { createRootRoute } from '@tanstack/react-router'; import { Outlet, createRootRoute, Link } from '@tanstack/react-router';
import { TanStackRouterDevtools } from '@tanstack/react-router-devtools'; import { TanStackRouterDevtools } from '@tanstack/react-router-devtools';
export const Route = createRootRoute({ export const Route = createRootRoute({
@@ -24,14 +24,17 @@ export const Route = createRootRoute({
<nav> <nav>
<ul> <ul>
<li> <li>
<a href={`/contacts/1`}>Your Name</a> <Link to="/contacts/$contractId" params={{ contractId: '1' }}>Your Name</Link>
</li> </li>
<li> <li>
<a href={`/contacts/2`}>Your Friend</a> <Link to="/contacts/$contractId" params={{ contractId: '2' }}>Your Friend</Link>
</li> </li>
</ul> </ul>
</nav> </nav>
</div> </div>
<div id={'detail'}>
<Outlet/>
</div>
<TanStackRouterDevtools/> <TanStackRouterDevtools/>
</> </>
), ),

View File

@@ -0,0 +1,101 @@
import { createFileRoute } from '@tanstack/react-router';
import type { ContactRecord } from "@/data.ts";
export const Route = createFileRoute('/contacts/$contractId')({
component: Contact,
});
function Contact() {
const contact = {
first: "Your",
last: "Name",
avatar: "https://placecats.com/200/200",
twitter: "your_handle",
notes: "Some notes",
favorite: true,
};
return (
<div id="contact">
<div>
<img
alt={`${contact.first} ${contact.last} avatar`}
key={contact.avatar}
src={contact.avatar}
/>
</div>
<div>
<h1>
{contact.first || contact.last ? (
<>
{contact.first} {contact.last}
</>
) : (
<i>No Name</i>
)}
<Favorite contact={contact}/>
</h1>
{contact.twitter ? (
<p>
<a
href={`https://twitter.com/${contact.twitter}`}
>
{contact.twitter}
</a>
</p>
) : null}
{contact.notes ? <p>{contact.notes}</p> : null}
<div>
<form action="edit">
<button type="submit">Edit</button>
</form>
<form
action="destroy"
method="post"
onSubmit={(event) => {
const response = confirm(
"Please confirm you want to delete this record."
);
if (!response) {
event.preventDefault();
}
}}
>
<button type="submit">Delete</button>
</form>
</div>
</div>
</div>
);
}
function Favorite(
{
contact,
}: {
contact: Pick<ContactRecord, "favorite">;
}
) {
const favorite = contact.favorite;
return (
<form method="post">
<button
aria-label={
favorite
? "Remove from favorites"
: "Add to favorites"
}
name="favorite"
value={favorite ? "false" : "true"}
>
{favorite ? "★" : "☆"}
</button>
</form>
);
}