This repository was archived by the owner on Feb 11, 2025. It is now read-only.
forked from trpc/trpc
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(
next
): experimental server actions (trpc#4359)
- Loading branch information
Showing
54 changed files
with
1,833 additions
and
173 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,58 +1,34 @@ | ||
import { Suspense } from 'react'; | ||
import { api } from 'trpc-api'; | ||
import { ClientGreeting } from './ClientGreeting'; | ||
import { ServerGreeting } from './ServerGreeting'; | ||
|
||
export default async function Home() { | ||
const promise = new Promise(async (resolve) => { | ||
await new Promise((r) => setTimeout(r, 1000)); // wait for demo purposes | ||
resolve(api.greeting.query({ text: 'streamed server data' })); | ||
}); | ||
import Link from 'next/link'; | ||
|
||
export default function Index() { | ||
return ( | ||
<main | ||
<ul | ||
style={{ | ||
width: '100vw', | ||
height: '100vh', | ||
display: 'flex', | ||
justifyContent: 'center', | ||
alignItems: 'center', | ||
fontSize: '1.1rem', | ||
listStyle: 'disc', | ||
listStylePosition: 'inside', | ||
padding: 0, | ||
}} | ||
> | ||
<div | ||
style={{ | ||
width: '12rem', | ||
padding: '1rem', | ||
background: '#e5e5e5', | ||
borderRadius: '0.5rem', | ||
}} | ||
> | ||
<div> | ||
<Suspense fallback={<>Loading client...</>}> | ||
<ClientGreeting /> | ||
</Suspense> | ||
</div> | ||
|
||
<div> | ||
<Suspense fallback={<>Loading Server...</>}> | ||
{/* @ts-expect-error RSC + TS not friends yet */} | ||
<ServerGreeting /> | ||
</Suspense> | ||
</div> | ||
<div> | ||
<Suspense fallback={<>Loading stream...</>}> | ||
{/** @ts-expect-error - Async Server Component */} | ||
<StreamedSC promise={promise} /> | ||
</Suspense> | ||
</div> | ||
</div> | ||
</main> | ||
<li> | ||
<Link | ||
href="/rsc" | ||
style={{ | ||
color: 'hsla(210, 16%, 80%, 1)', | ||
}} | ||
> | ||
React Server Components | ||
</Link> | ||
</li> | ||
<li> | ||
<Link | ||
href="/server-action" | ||
style={{ | ||
color: 'hsla(210, 16%, 80%, 1)', | ||
}} | ||
> | ||
Server Action | ||
</Link> | ||
</li> | ||
</ul> | ||
); | ||
} | ||
|
||
async function StreamedSC(props: { promise: Promise<string> }) { | ||
const data = await props.promise; | ||
|
||
return <div>{data}</div>; | ||
} |
File renamed without changes.
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
import { Suspense } from 'react'; | ||
import { api } from 'trpc-api'; | ||
import { TestMutation } from '../TestMutation'; | ||
import { ClientGreeting } from './ClientGreeting'; | ||
import { ServerGreeting } from './ServerGreeting'; | ||
|
||
export default async function Home() { | ||
const promise = new Promise(async (resolve) => { | ||
await new Promise((r) => setTimeout(r, 1000)); // wait for demo purposes | ||
resolve(api.greeting.query({ text: 'streamed server data' })); | ||
}); | ||
|
||
return ( | ||
<> | ||
<div> | ||
<Suspense fallback={<>Loading client...</>}> | ||
<ClientGreeting /> | ||
</Suspense> | ||
</div> | ||
|
||
<div> | ||
<Suspense fallback={<>Loading Server...</>}> | ||
{/* @ts-expect-error RSC + TS not friends yet */} | ||
<ServerGreeting /> | ||
</Suspense> | ||
</div> | ||
<div> | ||
<Suspense fallback={<>Loading stream...</>}> | ||
{/** @ts-expect-error - Async Server Component */} | ||
<StreamedSC promise={promise} /> | ||
</Suspense> | ||
</div> | ||
</> | ||
); | ||
} | ||
|
||
async function StreamedSC(props: { promise: Promise<string> }) { | ||
const data = await props.promise; | ||
|
||
return <div>{data}</div>; | ||
} |
32 changes: 32 additions & 0 deletions
32
examples/.experimental/next-app-dir/src/app/server-action/FormWithUseActionExample.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
'use client'; | ||
|
||
import { useAction } from 'trpc-api'; | ||
import { testAction } from './_actions'; | ||
|
||
export function FormWithUseActionExample() { | ||
const mutation = useAction(testAction); | ||
return ( | ||
<> | ||
<p>Check the console for the logger output.</p> | ||
<form | ||
action={testAction} | ||
onSubmit={(e) => { | ||
e.preventDefault(); | ||
const formData = new FormData(e.currentTarget); | ||
mutation.mutate(formData); | ||
}} | ||
> | ||
<input type="text" name="text" /> | ||
<button type="submit">Run server action raw debugging</button> | ||
|
||
<pre | ||
style={{ | ||
overflowX: 'scroll', | ||
}} | ||
> | ||
{JSON.stringify(mutation, null, 4)} | ||
</pre> | ||
</form> | ||
</> | ||
); | ||
} |
42 changes: 42 additions & 0 deletions
42
examples/.experimental/next-app-dir/src/app/server-action/RawExample.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
'use client'; | ||
|
||
import { useState } from 'react'; | ||
import { testAction } from './_actions'; | ||
|
||
export function RawExample() { | ||
const [text, setText] = useState(''); | ||
|
||
return ( | ||
<> | ||
<label> | ||
Text to send: <br /> | ||
<input | ||
type="text" | ||
value={text} | ||
onChange={(e) => setText(e.target.value)} | ||
/> | ||
</label> | ||
<br /> | ||
<button | ||
onClick={async () => { | ||
const res = await testAction({ | ||
text, | ||
}); | ||
console.log('result', res); | ||
// ^? | ||
if ('result' in res) { | ||
res.result; | ||
res.result.data; | ||
// ^? | ||
} else { | ||
res.error; | ||
// ^? | ||
} | ||
alert('Check console'); | ||
}} | ||
> | ||
Run server action raw debugging | ||
</button> | ||
</> | ||
); | ||
} |
19 changes: 19 additions & 0 deletions
19
examples/.experimental/next-app-dir/src/app/server-action/RawFormExample.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
'use client'; | ||
|
||
import { testAction } from './_actions'; | ||
|
||
export function RawFormExample() { | ||
return ( | ||
<> | ||
<p> | ||
Check the network tab and the server console to see that we called this. | ||
If you don not pass an input, it will fail validation and not reach the | ||
procedure. | ||
</p> | ||
<form action={testAction}> | ||
<input type="text" name="text" /> | ||
<button type="submit">Run server action raw debugging</button> | ||
</form> | ||
</> | ||
); | ||
} |
21 changes: 21 additions & 0 deletions
21
examples/.experimental/next-app-dir/src/app/server-action/ReactHookFormExample.action.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
'use server'; | ||
|
||
import { z } from 'zod'; | ||
import { createAction, publicProcedure } from '~/server/trpc'; | ||
import { rhfActionSchema } from './ReactHookFormExample.schema'; | ||
|
||
/** | ||
* Either inline procedures using trpc's flexible | ||
* builder api, with input parsers and middleware | ||
* Wrap the procedure in a `createAction` call to | ||
* make it server-action friendly | ||
*/ | ||
export const rhfAction = createAction( | ||
publicProcedure.input(rhfActionSchema).mutation(async (opts) => { | ||
console.log('testMutation called', opts); | ||
return { | ||
text: `Hello ${opts.input.text}`, | ||
date: new Date(), | ||
}; | ||
}), | ||
); |
5 changes: 5 additions & 0 deletions
5
examples/.experimental/next-app-dir/src/app/server-action/ReactHookFormExample.schema.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
import { z } from 'zod'; | ||
|
||
export const rhfActionSchema = z.object({ | ||
text: z.string().min(1), | ||
}); |
Oops, something went wrong.