Skip to content

Commit aea7d81

Browse files
authored
feat: add useQuery example (#19)
* feat: add useQuery example * fix: fix file structure/routing * feat: auto select first cast member * chore: update vercel config for rewrites * chore: update button w/ clearer label
1 parent d8ed4d4 commit aea7d81

File tree

5 files changed

+160
-1
lines changed

5 files changed

+160
-1
lines changed

sdk-explorer/src/App.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { BrowserRouter, Link, Route, Routes } from 'react-router'
44
import DocumentTable from './document-collections/DocumentTable/DocumentTable'
55
import PreviewGrid from './document-collections/PreviewGrid/PreviewGrid'
66
import PreviewList from './document-collections/PreviewList/PreviewList'
7+
import MoviesByActor from './groq/MoviesByActor/MoviesByActor'
78
import Home from './Home'
89

910
export default function App() {
@@ -58,6 +59,7 @@ export default function App() {
5859
path='/document-collections/document-table'
5960
element={<DocumentTable />}
6061
/>
62+
<Route path='/groq/movies-by-actor' element={<MoviesByActor />} />
6163
</Routes>
6264
</Card>
6365
</BrowserRouter>

sdk-explorer/src/Home.tsx

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,26 @@ export default function Home() {
6565
</Stack>
6666
</Card>
6767
</Stack>
68+
69+
<Stack space={5} paddingY={4}>
70+
<Card padding={4} radius={2} shadow={3}>
71+
<Stack space={4}>
72+
<Text as='h2' size={4} weight='medium'>
73+
GROQ
74+
</Text>
75+
76+
<Stack space={3}>
77+
<ExampleCard
78+
to='/groq/movies-by-actor'
79+
title='Movies by actor'
80+
description='Use multiple useQuery hooks to fetch and filter data'
81+
hooks={['useQuery']}
82+
styling='Sanity UI'
83+
/>
84+
</Stack>
85+
</Stack>
86+
</Card>
87+
</Stack>
6888
</Container>
6989
)
7090
}

sdk-explorer/src/ViewCode.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ export default function ViewCode({ url }: { url: string }) {
1111
href={url}
1212
target='_blank'
1313
mode='ghost'
14-
text='View on GitHub'
14+
text='View the code on GitHub'
1515
fontSize={2}
1616
padding={4}
1717
iconRight={LaunchIcon}
Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
import { useQuery } from '@sanity/sdk-react'
2+
import {
3+
Avatar,
4+
Card,
5+
Heading,
6+
Inline,
7+
Label,
8+
Select,
9+
Stack,
10+
Text,
11+
} from '@sanity/ui'
12+
import { useState } from 'react'
13+
import ExampleLayout from '../../ExampleLayout'
14+
15+
interface CastMember {
16+
_id: string
17+
name: string
18+
photo: string
19+
}
20+
21+
interface Movie {
22+
_id: string
23+
title: string
24+
posterImage: string
25+
releaseDate: string
26+
}
27+
28+
export default function MoviesByActor() {
29+
// Get a list of people who are referenced as cast members in more than 1 movie
30+
const { data: castMembers } = useQuery<CastMember[]>(
31+
`*[_type == "person" && count(*[_type == "movie" && ^._id in castMembers[].person._ref]) > 1] {
32+
_id,
33+
name,
34+
'photo': image.asset->url
35+
}`
36+
)
37+
38+
// Create a state variable to store the selected cast member's ID
39+
// Initialize it with the ID of the first cast member
40+
const [castMemberId, setCastMemberId] = useState<string>(
41+
() => castMembers?.[0]?._id
42+
)
43+
44+
// Construct another query for movies that the cast member has appeared in
45+
// by passing the cast member's ID as a parameter to the query
46+
const { data: castMemberMovies } = useQuery<Movie[]>(
47+
`*[_type == "movie" && $castMemberId in castMembers[].person._ref]{
48+
_id,
49+
title,
50+
'posterImage': poster.asset->url,
51+
releaseDate,
52+
}`,
53+
{
54+
params: {
55+
castMemberId: castMemberId,
56+
},
57+
}
58+
)
59+
60+
return (
61+
<ExampleLayout
62+
title='Movies by actor'
63+
codeUrl='https://github.com/sanity-io/sdk-examples/blob/main/sdk-explorer/src/groq/MoviesByActor/MoviesByActor.tsx'
64+
hooks={['useQuery']}
65+
styling='Sanity UI'
66+
>
67+
<Stack space={5}>
68+
{/* Render a select element and populate it with an option for each cast member */}
69+
<Stack space={3}>
70+
<Label htmlFor='castMembers'>Select a cast member:</Label>
71+
<Card style={{ maxWidth: '48ch' }}>
72+
<Select
73+
id='castMembers'
74+
fontSize={2}
75+
padding={4}
76+
value={castMemberId}
77+
onChange={(e) =>
78+
setCastMemberId(
79+
castMembers?.find(
80+
(member) => member._id === e.currentTarget.value
81+
)?._id || ''
82+
)
83+
}
84+
>
85+
<option disabled value='default'>
86+
Cast members in more than 1 movie
87+
</option>
88+
{castMembers?.map((person) => (
89+
<option key={person._id} value={person._id}>
90+
{person.name}
91+
</option>
92+
))}
93+
</Select>
94+
</Card>
95+
</Stack>
96+
97+
{/* Render the selected cast member's movies */}
98+
<Stack space={4}>
99+
{castMemberId && (
100+
<Inline space={3}>
101+
{/* Resize and crop the cast member's photo using Sanity image transformations */}
102+
<Avatar
103+
size={3}
104+
src={`${castMembers?.find((member) => member._id === castMemberId)?.photo}?h=200&w=200&fit=min`}
105+
color='purple'
106+
/>
107+
<Heading as='h2'>
108+
{
109+
castMembers?.find((member) => member._id === castMemberId)
110+
?.name
111+
}{' '}
112+
stars in:
113+
</Heading>
114+
</Inline>
115+
)}
116+
{castMemberMovies?.map((movie) => (
117+
<Inline key={movie._id} space={3}>
118+
<img src={movie.posterImage} alt={movie.title} width={100} />
119+
<Stack space={3}>
120+
<Text weight='semibold'>{movie.title}</Text>
121+
<Text>{new Date(movie.releaseDate).getFullYear()}</Text>
122+
</Stack>
123+
</Inline>
124+
))}
125+
</Stack>
126+
</Stack>
127+
</ExampleLayout>
128+
)
129+
}

sdk-explorer/vercel.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"rewrites": [
3+
{
4+
"source": "/(.*)",
5+
"destination": "/index.html"
6+
}
7+
]
8+
}

0 commit comments

Comments
 (0)