React Query
React Query example
Demonstrates mutation, query, and streamed query.
Result
Query result: Loading...
Stream result: Loading...
Mutation result: None
Code
1import { get, post, prefix, openapi, type VovkRequest } from 'vovk';
2
3@prefix('hello-world')
4export default class HelloWorldController {
5 @openapi({
6 summary: 'Get a greeting',
7 description: 'Get a greeting from the server',
8 })
9 @get('greeting')
10 static getHello() {
11 return { greeting: 'Hello world!' };
12 }
13
14 @openapi({
15 summary: 'Post a greeting',
16 description: 'Post a greeting to the server',
17 })
18 @post('greeting')
19 static async postHello(req: VovkRequest<{ greeting: string }>) {
20 const { greeting } = await req.json();
21 return { greeting };
22 }
23}
1import { get, post, prefix, openapi, type VovkRequest } from 'vovk';
2
3@prefix('hello-world')
4export default class HelloWorldController {
5 @openapi({
6 summary: 'Get a greeting',
7 description: 'Get a greeting from the server',
8 })
9 @get('greeting')
10 static getHello() {
11 return { greeting: 'Hello world!' };
12 }
13
14 @openapi({
15 summary: 'Post a greeting',
16 description: 'Post a greeting to the server',
17 })
18 @post('greeting')
19 static async postHello(req: VovkRequest<{ greeting: string }>) {
20 const { greeting } = await req.json();
21 return { greeting };
22 }
23}
1import { get, post, prefix, openapi, type VovkRequest } from 'vovk';
2
3@prefix('hello-world')
4export default class HelloWorldController {
5 @openapi({
6 summary: 'Get a greeting',
7 description: 'Get a greeting from the server',
8 })
9 @get('greeting')
10 static getHello() {
11 return { greeting: 'Hello world!' };
12 }
13
14 @openapi({
15 summary: 'Post a greeting',
16 description: 'Post a greeting to the server',
17 })
18 @post('greeting')
19 static async postHello(req: VovkRequest<{ greeting: string }>) {
20 const { greeting } = await req.json();
21 return { greeting };
22 }
23}
1import { get, post, prefix, openapi, type VovkRequest } from 'vovk';
2
3@prefix('hello-world')
4export default class HelloWorldController {
5 @openapi({
6 summary: 'Get a greeting',
7 description: 'Get a greeting from the server',
8 })
9 @get('greeting')
10 static getHello() {
11 return { greeting: 'Hello world!' };
12 }
13
14 @openapi({
15 summary: 'Post a greeting',
16 description: 'Post a greeting to the server',
17 })
18 @post('greeting')
19 static async postHello(req: VovkRequest<{ greeting: string }>) {
20 const { greeting } = await req.json();
21 return { greeting };
22 }
23}
1import { get, prefix, openapi } from 'vovk';
2
3type Token = { message: string };
4
5@prefix('stream')
6export default class StreamController {
7 @openapi({
8 summary: 'Stream tokens',
9 description: 'Stream tokens to the client',
10 })
11 @get('tokens', { cors: true })
12 static async *streamTokens() {
13 const tokens: Token[] = [
14 { message: 'Hello,' },
15 { message: ' World' },
16 { message: ' from' },
17 { message: ' Stream' },
18 { message: '!' },
19 ];
20
21 for (const token of tokens) {
22 yield token;
23 await new Promise((resolve) => setTimeout(resolve, 300));
24 }
25 }
26}
1import { get, prefix, openapi } from 'vovk';
2
3type Token = { message: string };
4
5@prefix('stream')
6export default class StreamController {
7 @openapi({
8 summary: 'Stream tokens',
9 description: 'Stream tokens to the client',
10 })
11 @get('tokens', { cors: true })
12 static async *streamTokens() {
13 const tokens: Token[] = [
14 { message: 'Hello,' },
15 { message: ' World' },
16 { message: ' from' },
17 { message: ' Stream' },
18 { message: '!' },
19 ];
20
21 for (const token of tokens) {
22 yield token;
23 await new Promise((resolve) => setTimeout(resolve, 300));
24 }
25 }
26}
1import { get, prefix, openapi } from 'vovk';
2
3type Token = { message: string };
4
5@prefix('stream')
6export default class StreamController {
7 @openapi({
8 summary: 'Stream tokens',
9 description: 'Stream tokens to the client',
10 })
11 @get('tokens', { cors: true })
12 static async *streamTokens() {
13 const tokens: Token[] = [
14 { message: 'Hello,' },
15 { message: ' World' },
16 { message: ' from' },
17 { message: ' Stream' },
18 { message: '!' },
19 ];
20
21 for (const token of tokens) {
22 yield token;
23 await new Promise((resolve) => setTimeout(resolve, 300));
24 }
25 }
26}
1import { get, prefix, openapi } from 'vovk';
2
3type Token = { message: string };
4
5@prefix('stream')
6export default class StreamController {
7 @openapi({
8 summary: 'Stream tokens',
9 description: 'Stream tokens to the client',
10 })
11 @get('tokens', { cors: true })
12 static async *streamTokens() {
13 const tokens: Token[] = [
14 { message: 'Hello,' },
15 { message: ' World' },
16 { message: ' from' },
17 { message: ' Stream' },
18 { message: '!' },
19 ];
20
21 for (const token of tokens) {
22 yield token;
23 await new Promise((resolve) => setTimeout(resolve, 300));
24 }
25 }
26}
1'use client';
2import { HelloWorldRPC, StreamRPC } from 'vovk-client';
3import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
4import { useState } from 'react';
5
6export function Example() {
7 const query = HelloWorldRPC.getHello.useQuery();
8 const stream = StreamRPC.streamTokens.useQuery();
9 const mutation = HelloWorldRPC.postHello.useMutation();
10
11 const [userInput, setUserInput] = useState('');
12
13 return (
14 <div>
15 <div>Query result: {query.data?.greeting ?? <em>Loading...</em>}</div>
16 <div>
17 Stream result: {stream.data?.map(({ message }, i) => <span key={i}>{message}</span>) ?? <em>Loading...</em>}
18 </div>
19 <div>
20 Mutation result: {mutation.data?.greeting ?? (mutation.isPending ? <em>Loading...</em> : <em>None</em>)}
21 </div>
22 <div className="input-group">
23 <input
24 type="text"
25 placeholder="Type a greeting..."
26 value={userInput}
27 onChange={(e) => setUserInput(e.currentTarget.value)}
28 />
29 <button onClick={() => mutation.mutate({ body: { greeting: userInput } })}>Mutate</button>
30 </div>
31 </div>
32 );
33}
34
35const queryClient = new QueryClient();
36
37export default function ReactQueryExample() {
38 return (
39 <QueryClientProvider client={queryClient}>
40 <Example />
41 </QueryClientProvider>
42 );
43}
1'use client';
2import { HelloWorldRPC, StreamRPC } from 'vovk-client';
3import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
4import { useState } from 'react';
5
6export function Example() {
7 const query = HelloWorldRPC.getHello.useQuery();
8 const stream = StreamRPC.streamTokens.useQuery();
9 const mutation = HelloWorldRPC.postHello.useMutation();
10
11 const [userInput, setUserInput] = useState('');
12
13 return (
14 <div>
15 <div>Query result: {query.data?.greeting ?? <em>Loading...</em>}</div>
16 <div>
17 Stream result: {stream.data?.map(({ message }, i) => <span key={i}>{message}</span>) ?? <em>Loading...</em>}
18 </div>
19 <div>
20 Mutation result: {mutation.data?.greeting ?? (mutation.isPending ? <em>Loading...</em> : <em>None</em>)}
21 </div>
22 <div className="input-group">
23 <input
24 type="text"
25 placeholder="Type a greeting..."
26 value={userInput}
27 onChange={(e) => setUserInput(e.currentTarget.value)}
28 />
29 <button onClick={() => mutation.mutate({ body: { greeting: userInput } })}>Mutate</button>
30 </div>
31 </div>
32 );
33}
34
35const queryClient = new QueryClient();
36
37export default function ReactQueryExample() {
38 return (
39 <QueryClientProvider client={queryClient}>
40 <Example />
41 </QueryClientProvider>
42 );
43}
1'use client';
2import { HelloWorldRPC, StreamRPC } from 'vovk-client';
3import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
4import { useState } from 'react';
5
6export function Example() {
7 const query = HelloWorldRPC.getHello.useQuery();
8 const stream = StreamRPC.streamTokens.useQuery();
9 const mutation = HelloWorldRPC.postHello.useMutation();
10
11 const [userInput, setUserInput] = useState('');
12
13 return (
14 <div>
15 <div>Query result: {query.data?.greeting ?? <em>Loading...</em>}</div>
16 <div>
17 Stream result: {stream.data?.map(({ message }, i) => <span key={i}>{message}</span>) ?? <em>Loading...</em>}
18 </div>
19 <div>
20 Mutation result: {mutation.data?.greeting ?? (mutation.isPending ? <em>Loading...</em> : <em>None</em>)}
21 </div>
22 <div className="input-group">
23 <input
24 type="text"
25 placeholder="Type a greeting..."
26 value={userInput}
27 onChange={(e) => setUserInput(e.currentTarget.value)}
28 />
29 <button onClick={() => mutation.mutate({ body: { greeting: userInput } })}>Mutate</button>
30 </div>
31 </div>
32 );
33}
34
35const queryClient = new QueryClient();
36
37export default function ReactQueryExample() {
38 return (
39 <QueryClientProvider client={queryClient}>
40 <Example />
41 </QueryClientProvider>
42 );
43}
1'use client';
2import { HelloWorldRPC, StreamRPC } from 'vovk-client';
3import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
4import { useState } from 'react';
5
6export function Example() {
7 const query = HelloWorldRPC.getHello.useQuery();
8 const stream = StreamRPC.streamTokens.useQuery();
9 const mutation = HelloWorldRPC.postHello.useMutation();
10
11 const [userInput, setUserInput] = useState('');
12
13 return (
14 <div>
15 <div>Query result: {query.data?.greeting ?? <em>Loading...</em>}</div>
16 <div>
17 Stream result: {stream.data?.map(({ message }, i) => <span key={i}>{message}</span>) ?? <em>Loading...</em>}
18 </div>
19 <div>
20 Mutation result: {mutation.data?.greeting ?? (mutation.isPending ? <em>Loading...</em> : <em>None</em>)}
21 </div>
22 <div className="input-group">
23 <input
24 type="text"
25 placeholder="Type a greeting..."
26 value={userInput}
27 onChange={(e) => setUserInput(e.currentTarget.value)}
28 />
29 <button onClick={() => mutation.mutate({ body: { greeting: userInput } })}>Mutate</button>
30 </div>
31 </div>
32 );
33}
34
35const queryClient = new QueryClient();
36
37export default function ReactQueryExample() {
38 return (
39 <QueryClientProvider client={queryClient}>
40 <Example />
41 </QueryClientProvider>
42 );
43}
1// @ts-check
2/** @type {import('vovk').VovkConfig} */
3const config = {
4 // you can use NEXT_PUBLIC_VERCEL_URL env var for preview deployments on Vercel
5 origin: process.env.VERCEL_ENV
6 ? `https://vovk-examples.vercel.app`
7 : 'http://localhost:' + (process.env.PORT ?? 3000),
8 imports: {
9 createRPC: 'vovk-react-query',
10 validateOnClient: 'vovk-ajv',
11 },
12 bundle: {
13 readme: {
14 banner: `<p align="center">
15 <picture>
16 <source width="300" media="(prefers-color-scheme: dark)" srcset="https://vovk.dev/vovk-logo-white.svg">
17 <source width="300" media="(prefers-color-scheme: light)" srcset="https://vovk.dev/vovk-logo.svg">
18 <img width="300" alt="vovk" src="https://vovk.dev/vovk-logo.svg">
19 </picture><br>
20 <strong>RESTful + RPC = ♥️</strong>
21</p>
22
23<p align="center">
24 Back-end meta-framework for <a href="https://nextjs.org/docs/app">Next.js</a>
25</p>`,
26 },
27 },
28 emitConfig: true,
29 logLevel: 'debug',
30};
31
32export default config;
1// @ts-check
2/** @type {import('vovk').VovkConfig} */
3const config = {
4 // you can use NEXT_PUBLIC_VERCEL_URL env var for preview deployments on Vercel
5 origin: process.env.VERCEL_ENV
6 ? `https://vovk-examples.vercel.app`
7 : 'http://localhost:' + (process.env.PORT ?? 3000),
8 imports: {
9 createRPC: 'vovk-react-query',
10 validateOnClient: 'vovk-ajv',
11 },
12 bundle: {
13 readme: {
14 banner: `<p align="center">
15 <picture>
16 <source width="300" media="(prefers-color-scheme: dark)" srcset="https://vovk.dev/vovk-logo-white.svg">
17 <source width="300" media="(prefers-color-scheme: light)" srcset="https://vovk.dev/vovk-logo.svg">
18 <img width="300" alt="vovk" src="https://vovk.dev/vovk-logo.svg">
19 </picture><br>
20 <strong>RESTful + RPC = ♥️</strong>
21</p>
22
23<p align="center">
24 Back-end meta-framework for <a href="https://nextjs.org/docs/app">Next.js</a>
25</p>`,
26 },
27 },
28 emitConfig: true,
29 logLevel: 'debug',
30};
31
32export default config;
1// @ts-check
2/** @type {import('vovk').VovkConfig} */
3const config = {
4 // you can use NEXT_PUBLIC_VERCEL_URL env var for preview deployments on Vercel
5 origin: process.env.VERCEL_ENV
6 ? `https://vovk-examples.vercel.app`
7 : 'http://localhost:' + (process.env.PORT ?? 3000),
8 imports: {
9 createRPC: 'vovk-react-query',
10 validateOnClient: 'vovk-ajv',
11 },
12 bundle: {
13 readme: {
14 banner: `<p align="center">
15 <picture>
16 <source width="300" media="(prefers-color-scheme: dark)" srcset="https://vovk.dev/vovk-logo-white.svg">
17 <source width="300" media="(prefers-color-scheme: light)" srcset="https://vovk.dev/vovk-logo.svg">
18 <img width="300" alt="vovk" src="https://vovk.dev/vovk-logo.svg">
19 </picture><br>
20 <strong>RESTful + RPC = ♥️</strong>
21</p>
22
23<p align="center">
24 Back-end meta-framework for <a href="https://nextjs.org/docs/app">Next.js</a>
25</p>`,
26 },
27 },
28 emitConfig: true,
29 logLevel: 'debug',
30};
31
32export default config;
1// @ts-check
2/** @type {import('vovk').VovkConfig} */
3const config = {
4 // you can use NEXT_PUBLIC_VERCEL_URL env var for preview deployments on Vercel
5 origin: process.env.VERCEL_ENV
6 ? `https://vovk-examples.vercel.app`
7 : 'http://localhost:' + (process.env.PORT ?? 3000),
8 imports: {
9 createRPC: 'vovk-react-query',
10 validateOnClient: 'vovk-ajv',
11 },
12 bundle: {
13 readme: {
14 banner: `<p align="center">
15 <picture>
16 <source width="300" media="(prefers-color-scheme: dark)" srcset="https://vovk.dev/vovk-logo-white.svg">
17 <source width="300" media="(prefers-color-scheme: light)" srcset="https://vovk.dev/vovk-logo.svg">
18 <img width="300" alt="vovk" src="https://vovk.dev/vovk-logo.svg">
19 </picture><br>
20 <strong>RESTful + RPC = ♥️</strong>
21</p>
22
23<p align="center">
24 Back-end meta-framework for <a href="https://nextjs.org/docs/app">Next.js</a>
25</p>`,
26 },
27 },
28 emitConfig: true,
29 logLevel: 'debug',
30};
31
32export default config;
Last updated on