Skip to content

Commit b2d0822

Browse files
committed
update 04
1 parent b6ba80d commit b2d0822

12 files changed

Lines changed: 100 additions & 53 deletions

File tree

04-frameworks/08-nextjs/04-static-site-generation/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -457,7 +457,7 @@ export default nextConfig;
457457
>
458458
> [Next config file](https://nextjs.org/docs/app/api-reference/next-config-js)
459459
460-
Run app dev mode:
460+
Run app prod mode:
461461

462462
```bash
463463
npm run start:api-server

04-frameworks/17-tanstack-start/03-boilerplate/src/pods/car/api/car.api.ts

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,23 @@
11
import { ENV } from '#core/constants';
2+
import { createServerFn } from '@tanstack/react-start';
23
import { Car } from './car.api-model';
34

45
const url = `${ENV.BASE_API_URL}/cars`;
56

6-
export const getCar = async (id: string): Promise<Car> =>
7-
await fetch(`${url}/${id}`).then((response) => response.json());
7+
export const getCar = createServerFn()
8+
.inputValidator((data: { id: string }) => data)
9+
.handler(
10+
async ({ data }): Promise<Car> =>
11+
await fetch(`${url}/${data.id}`).then((response) => response.json())
12+
);
813

9-
export const bookCar = async (car: Car): Promise<boolean> => {
10-
await fetch(`${url}/${car.id}`, {
11-
method: 'PATCH',
12-
headers: { 'Content-Type': 'application/json' },
13-
body: JSON.stringify(car),
14+
export const bookCar = createServerFn({ method: 'POST' })
15+
.inputValidator((car: Car) => car)
16+
.handler(async ({ data }): Promise<boolean> => {
17+
await fetch(`${url}/${data.id}`, {
18+
method: 'PATCH',
19+
headers: { 'Content-Type': 'application/json' },
20+
body: JSON.stringify(data),
21+
});
22+
return true;
1423
});
15-
return true;
16-
};

04-frameworks/17-tanstack-start/03-boilerplate/src/pods/car/car.component.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
import React from 'react';
21
import { useNavigate } from '@tanstack/react-router';
2+
import React from 'react';
33
import * as api from './api';
4-
import * as viewModel from './car.vm';
54
import { mapCarFromVmToApi } from './car.mappers';
65
import classes from './car.module.css';
6+
import * as viewModel from './car.vm';
77

88
interface Props {
99
car: viewModel.Car;
@@ -16,7 +16,7 @@ export const Car: React.FC<Props> = (props) => {
1616
const handleBook = async () => {
1717
try {
1818
const apiCar = mapCarFromVmToApi({ ...car, isBooked: !car.isBooked });
19-
await api.bookCar(apiCar);
19+
await api.bookCar({ data: apiCar });
2020
navigate({ to: '/cars' });
2121
} catch (error) {
2222
console.error({ error });
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
PUBLIC_BASE_API_URL=http://localhost:3001/api
1+
BASE_API_URL=http://localhost:3001/api
22
PUBLIC_BASE_PICTURES_URL=http://localhost:3001

04-frameworks/17-tanstack-start/04-tanstack-start-migration/README.md

Lines changed: 52 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,10 @@ export function getRouter() {
7575
```
7676

7777
> `scrollRestoration` is optional, it enables automatic scroll position restoration when navigating simulating browser behavior.
78+
>
79+
> [Server entrypoint](https://tanstack.com/start/latest/docs/framework/react/guide/server-entry-point)
80+
>
81+
> [Client entrypoint](https://tanstack.com/start/latest/docs/framework/react/guide/client-entry-point)
7882
7983
If we run the app now, we should see it partially working:
8084

@@ -235,8 +239,51 @@ export const ENV = {
235239
```
236240

237241
> [Vite Env Variables](https://vite.dev/guide/env-and-mode)
238-
>
239-
> [Use server functions if we want execute code only on the server](https://tanstack.com/start/latest/docs/framework/react/guide/server-functions)
242+
243+
But if we want to execute it only in the server we can [use server functions](https://tanstack.com/start/latest/docs/framework/react/guide/server-functions):
244+
245+
_./src/pods/car-list/car-list.api.ts_
246+
247+
```diff
248+
import { ENV } from '#core/constants';
249+
import { Car } from './car-list.api-model';
250+
+ import { createServerFn } from '@tanstack/react-start';
251+
252+
const url = `${ENV.BASE_API_URL}/cars`;
253+
254+
- export const getCarList =
255+
+ export const getCarList = createServerFn().handler(
256+
async (): Promise<Car[]> =>
257+
await fetch(url).then((response) => response.json())
258+
+ );
259+
260+
```
261+
262+
Remove the environment variable prefixing:
263+
264+
_./.env.local_
265+
266+
```diff
267+
- PUBLIC_BASE_API_URL=http://localhost:3001/api
268+
+ BASE_API_URL=http://localhost:3001/api
269+
PUBLIC_BASE_PICTURES_URL=http://localhost:3001
270+
271+
```
272+
273+
_./src/core/env.constants.ts_
274+
275+
```diff
276+
export const ENV = {
277+
- BASE_API_URL:
278+
- process.env.PUBLIC_BASE_API_URL ||
279+
+ process.env.BASE_API_URL ||
280+
- import.meta.env.PUBLIC_BASE_API_URL ||
281+
'',
282+
...
283+
284+
```
285+
286+
> Check the Network tab in the browser dev tools, we should see that an special request is made to fetch the car list data from the server function endpoint.
240287
241288
Let's change the routes to apply styles and components that we already have in pods:
242289

@@ -271,6 +318,8 @@ function RouteComponent() {
271318
```
272319

273320
> [Migrating from Nextjs Guide](https://tanstack.com/start/latest/docs/framework/react/migrate-from-next-js)
321+
>
322+
> [CSS Modules FOUC (flash of unstyled content) issue still open](https://github.com/TanStack/router/issues/3023#issuecomment-2689163745)
274323
275324
Update the car list page:
276325

@@ -324,7 +373,7 @@ _./src/routes/cars/$id.tsx_
324373
import { createFileRoute } from '@tanstack/react-router';
325374

326375
export const Route = createFileRoute('/cars/$id')({
327-
+ loader: ({ params }) => api.getCar(params.id),
376+
+ loader: ({ params }) => api.getCar({ data: { id: params.id } }),
328377
+ head: ({ loaderData }) => ({
329378
+ meta: [{ title: `Rent a car - Car ${loaderData?.name} details` }],
330379
+ }),

04-frameworks/17-tanstack-start/04-tanstack-start-migration/index.html

Lines changed: 0 additions & 13 deletions
This file was deleted.

04-frameworks/17-tanstack-start/04-tanstack-start-migration/src/core/constants/env.constants.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
11
export const ENV = {
2-
BASE_API_URL:
3-
process.env.PUBLIC_BASE_API_URL ||
4-
import.meta.env.PUBLIC_BASE_API_URL ||
5-
'',
2+
BASE_API_URL: process.env.BASE_API_URL || '',
63
BASE_PICTURES_URL:
74
process.env.PUBLIC_BASE_PICTURES_URL ||
85
import.meta.env.PUBLIC_BASE_PICTURES_URL ||
Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
import { ENV } from '#core/constants';
22
import { Car } from './car-list.api-model';
3+
import { createServerFn } from '@tanstack/react-start';
34

45
const url = `${ENV.BASE_API_URL}/cars`;
56

6-
export const getCarList = async (): Promise<Car[]> =>
7-
await fetch(url).then((response) => response.json());
7+
export const getCarList = createServerFn().handler(
8+
async (): Promise<Car[]> =>
9+
await fetch(url).then((response) => response.json())
10+
);

04-frameworks/17-tanstack-start/04-tanstack-start-migration/src/pods/car/api/car.api.ts

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,23 @@
11
import { ENV } from '#core/constants';
2+
import { createServerFn } from '@tanstack/react-start';
23
import { Car } from './car.api-model';
34

45
const url = `${ENV.BASE_API_URL}/cars`;
56

6-
export const getCar = async (id: string): Promise<Car> =>
7-
await fetch(`${url}/${id}`).then((response) => response.json());
7+
export const getCar = createServerFn()
8+
.inputValidator((data: { id: string }) => data)
9+
.handler(
10+
async ({ data }): Promise<Car> =>
11+
await fetch(`${url}/${data.id}`).then((response) => response.json())
12+
);
813

9-
export const bookCar = async (car: Car): Promise<boolean> => {
10-
await fetch(`${url}/${car.id}`, {
11-
method: 'PATCH',
12-
headers: { 'Content-Type': 'application/json' },
13-
body: JSON.stringify(car),
14+
export const bookCar = createServerFn({ method: 'POST' })
15+
.inputValidator((car: Car) => car)
16+
.handler(async ({ data }): Promise<boolean> => {
17+
await fetch(`${url}/${data.id}`, {
18+
method: 'PATCH',
19+
headers: { 'Content-Type': 'application/json' },
20+
body: JSON.stringify(data),
21+
});
22+
return true;
1423
});
15-
return true;
16-
};

04-frameworks/17-tanstack-start/04-tanstack-start-migration/src/pods/car/car.component.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
import React from 'react';
21
import { useNavigate } from '@tanstack/react-router';
2+
import React from 'react';
33
import * as api from './api';
4-
import * as viewModel from './car.vm';
54
import { mapCarFromVmToApi } from './car.mappers';
65
import classes from './car.module.css';
6+
import * as viewModel from './car.vm';
77

88
interface Props {
99
car: viewModel.Car;
@@ -16,7 +16,7 @@ export const Car: React.FC<Props> = (props) => {
1616
const handleBook = async () => {
1717
try {
1818
const apiCar = mapCarFromVmToApi({ ...car, isBooked: !car.isBooked });
19-
await api.bookCar(apiCar);
19+
await api.bookCar({ data: apiCar });
2020
navigate({ to: '/cars' });
2121
} catch (error) {
2222
console.error({ error });

0 commit comments

Comments
 (0)