Using withDocument HOC to refer to the document in a preview component

14 replies
Last updated: Oct 27, 2022
Is it possible to refer to the
document
in the
preview
of the document (
childObject
->
preview
- line with
if (document.showCorrectness)
)?

export default {
    name: 'parentObject',
    title: 'Parent',
    type: 'document',
    fields: [
        {
            name: 'showCorrectness',
            title: 'Show Correctness',
            type: 'boolean',
        },
        {
            name: 'answers',
            title: 'Answers',
            type: 'array',
            of: [{ type: 'childObject' }],
        },
    ],
};

import React from 'react';

export default {
    name: 'childObject',
    title: 'Child Object',
    type: 'object',
    fields: [
        {
            title: 'Text',
            name: 'text',
            type: 'string',
        },
        {
            title: 'Is correct',
            name: 'isCorrect',
            type: 'boolean',
            hidden: ({ document }) => {
                return !document.showCorrectness;
            },
            validation: (Rule) =>
                Rule.custom((correctness, { document }) => {
                    if (!document.showCorrectness) {
                        return true;
                    }

                    return 'Correctness required';
                }),
        },
    ],
    preview: {
        select: {
            isCorrect: 'isCorrect',
            text: 'text',
        },
        prepare(child) {
            const PARENT_ICON = {
                correct: '✅',
                incorrect: '❌',
                neutral: '🔵',
            };

            let parentIcon = PARENT_ICON.neutral;

            if (document.showCorrectness) {
                parentIcon = child.isCorrect ? PARENT_ICON.correct : PARENT_ICON.incorrect;
            }

            return {
                title: child.text,
                media: <p>{parentIcon}</p>,
            };
        },
    },
};
AI Update

The short answer is no, you cannot directly access the parent document object in the prepare function of a child object's preview configuration. The document variable in your prepare function is undefined because the standard preview select and prepare functions only have access to the fields you explicitly select from the current object.

However, there's a modern solution for Studio v3: use a custom preview component with the useFormValue hook.

Solution: Custom Preview Component (Studio v3)

Instead of using the standard preview.prepare function, create a custom preview component that can access the parent document's fields:

import React from 'react';
import { useFormValue } from 'sanity';

const ChildObjectPreview = (props) => {
  // Access the parent document's showCorrectness field
  const showCorrectness = useFormValue(['showCorrectness']);
  const { isCorrect, text } = props;

  const PARENT_ICON = {
    correct: '✅',
    incorrect: '❌',
    neutral: '🔵',
  };

  let parentIcon = PARENT_ICON.neutral;
  
  if (showCorrectness) {
    parentIcon = isCorrect ? PARENT_ICON.correct : PARENT_ICON.incorrect;
  }

  return props.renderDefault({
    ...props,
    title: text,
    media: <p>{parentIcon}</p>,
  });
};

export default {
  name: 'childObject',
  title: 'Child Object',
  type: 'object',
  fields: [
    // ... your fields
  ],
  components: {
    preview: ChildObjectPreview
  }
};

The useFormValue hook allows you to access any field in the parent document by providing the field path as an array. For accessing nested parent fields, you can use useFormValue(props.path.slice(0, -1)) to get the immediate parent object.

Why the Standard Preview Doesn't Work

The standard preview configuration with select and prepare is designed to work only with the current object's fields and referenced documents. It doesn't have access to the parent document context by design—this keeps previews performant and predictable.

The custom preview component approach is the recommended solution when you need access to parent document fields or other form state in Studio v3.

user J
could you take a look here? 🙏 You always have some good advice
I will have a look tomorrow hopefully 🙂 I am so busy atm but will def look into this more ..
okay I had a glance: where do you need the preview to be in?
Because as far as I can see you could define preview half here and there…I could need an actual example i think, and you might want to look into this here… 1mom
you’re in luck 😉 I have an Idea!using
withDocument
HOC in the preview component and using this instead of prepare etc. When its good enough for inputs , it will be okay in previews (i bet).But still give me something to wrap my head around
🙏
It works! 🙆‍♀️ thank you
user J
crazy scientist
,wohoo I am on a good streak :saluting_face:🥰
Fun
withDocument
works so well in many different places.But just as a last fyi: I would not use it for a lot of previews instead of the schema preview unless you test it thoroughly for performance etc.
Thank you again! I have posted my solution here , maybe it will be useful to someone 🤗
You should also post this in the sanity exchange, through the community studio 💪❤️
Really cool thing btw!
I wanted to do it through community studio, but there it is impossible to add images (and in this example they best illustrate the capabilities of the tool)
Ah okay, we are working on the community studio atm so this will change soon … but we will put a pin in it. OR you do not add it as a snippet, but as a guide, which is basically is, so then you have images and more at your disposal 🙂we need more female devs publishing things!

Sanity – Build the way you think, not the way your CMS thinks

Sanity is the developer-first content operating system that gives you complete control. Schema-as-code, GROQ queries, and real-time APIs mean no more workarounds or waiting for deployments. Free to start, scale as you grow.

Was this answer helpful?