Lesson
6
useDocument
Log in to watch a video walkthrough of this lesson
Log in

Fetch content with real-time and optimistic updates when edits are made—locally or remotely.
Log in to mark your progress for each Lesson and Task
This hook is similar to useDocumentProjection
in the previous lesson. However useDocument
will sync with both local and remote changes to the document. Because of this it can be more memory intensive, this hook should be used sparingly.
That is why in this course you've used useDocumentProjection
for the document list— which could eventually render 100's of documents—while only using useDocument
for the one document rendered in the editing form.
Create a new component to query for the entire document from its handle.
import { DocumentHandle, useDocument } from "@sanity/sdk-react"import { Card, Flex, Stack, Text, Container } from "@sanity/ui"
import { StatusBadge } from "./StatusBadge"
type FeedbackEditProps = { selectedFeedback: DocumentHandle}
export function FeedbackEdit({ selectedFeedback }: FeedbackEditProps) { const { data } = useDocument({ ...selectedFeedback })
if (!data) { return null }
// Ensure type safety for all fields const author = typeof data.author === "string" ? data.author : "" const email = typeof data.email === "string" ? data.email : "" const content = typeof data.content === "string" ? data.content : "" const createdAt = typeof data._createdAt === "string" ? data._createdAt.split("T")[0] : "" const status = typeof data.status === "string" ? data.status : "pending" const sentiment = typeof data.sentiment === "string" ? data.sentiment : "" const notes = typeof data.notes === "string" ? data.notes : "" const assignee = typeof data.assignee === "string" ? data.assignee : ""
return ( <Container width={1}> <Card padding={[0, 0, 4, 5]}> <Card padding={[0, 0, 4, 5]} radius={3} shadow={[0, 0, 2]}> <Stack space={5}> <Flex align="center" justify="space-between"> <Stack space={3}> <Text size={3} weight="semibold"> {author} </Text> <Text size={1} muted> {email} {createdAt} </Text> </Stack> <StatusBadge status={status} fontSize={2} /> </Flex>
<Stack space={3}> <Card padding={4} radius={2} tone="transparent"> <Text size={3}>{content}</Text> </Card> </Stack>
{/* In the next lessons... */} {/* Sentiment, Notes, Assignee, Actions */} </Stack> </Card> </Card> </Container> )}
Update the parent Feedback component to render the editing form
import { Suspense, useState } from "react"import { DocumentHandle } from "@sanity/sdk-react"import { Card, Flex, Grid, Spinner } from "@sanity/ui"import { styled } from "styled-components"
import { FeedbackList } from "./FeedbackList"import { FeedbackEdit } from "./FeedbackEdit"
const ScreenHeightCard = styled(Card)` height: 100vh; overflow: scroll;`
export function Feedback() { const [selectedFeedback, setSelectedFeedback] = useState<DocumentHandle | null>(null)
return ( <Grid columns={5}> <ScreenHeightCard columnStart={1} columnEnd={3}> <Suspense fallback={<Loading />}> <FeedbackList setSelectedFeedback={setSelectedFeedback} selectedFeedback={selectedFeedback} /> </Suspense> </ScreenHeightCard> <ScreenHeightCard borderLeft columnStart={3} columnEnd={6}> <Suspense fallback={<Loading />}> {selectedFeedback ? ( <FeedbackEdit selectedFeedback={selectedFeedback} /> ) : null} </Suspense> </ScreenHeightCard> </Grid> )}
function Loading() { return ( <Flex justify="center" align="center" width="fill" height="fill"> <Spinner /> </Flex> )}
You should now be able to click each document in the list, and open the editing form on the right. The values in this form have a real-time subscription to changes in the Content Lake, as well as an in-memory optimistic cache to render any edits as they happen.
It's time to start editing documents with the App SDK.
You have 2 uncompleted tasks in this lesson
0 of 2