Custom Studio input implementation issue with useFormValue in Sanity

2 replies
Last updated: Jun 21, 2024
Hello all, I am trying to implement a custom Studio input. I have a document where there is an array of objects, and in this objects there is a reference field and a field with the custom component. The idea is to fetch the referenced document and display a select based on some values of that document. The problem I am having is that with
useFormValue
it does not seems as I can identify which object is being rendered. So the component does not know in which object resides or from which object read the reference field. Keep in mind each object migh have different values in that reference field.
Does someone have any idea on how to overcome this?
AI Update

I can help you with this! The key to solving your problem is understanding that your custom component receives a path prop that tells you exactly where in the document structure you are, including which array item is being rendered.

Here's how to access the reference field from the same array object:

import { useFormValue } from 'sanity'

const MyCustomComponent = (props) => {
  const { path } = props
  
  // Get the path to the parent object (the array item)
  // If path is ['myArray', {_key: 'abc123'}, 'myCustomField']
  // parentPath will be ['myArray', {_key: 'abc123'}]
  const parentPath = path.slice(0, -1)
  
  // Access the entire parent object
  const parentObject = useFormValue(parentPath)
  
  // Or access the specific reference field in the same object
  const referenceField = useFormValue([...parentPath, 'referenceFieldName'])
  
  // Now you can use the reference to fetch and display your select options
  useEffect(() => {
    if (referenceField?._ref) {
      // Fetch the referenced document and build your select options
      client.fetch('*[_id == $ref][0]', { ref: referenceField._ref })
        .then(referencedDoc => {
          // Use referencedDoc to populate your select
        })
    }
  }, [referenceField])
  
  // ... rest of your component
}

The crucial insight is that the path prop contains the full path including the array item's _key, which uniquely identifies which object in the array is being rendered. By using path.slice(0, -1), you get the path to the parent object, and then you can access any sibling field within that same array item.

For example, if your schema looks like:

{
  name: 'items',
  type: 'array',
  of: [{
    type: 'object',
    fields: [
      {
        name: 'myReference',
        type: 'reference',
        to: [{type: 'someDocument'}]
      },
      {
        name: 'myCustomField',
        type: 'string',
        components: {
          input: MyCustomComponent
        }
      }
    ]
  }]
}

Then in your custom component, useFormValue([...parentPath, 'myReference']) will give you the reference field value for that specific array item.

This approach is covered in the useFormValue documentation and specifically addresses working with arrays as mentioned in this community answer.

Your component will receive a
path
array in your
props
. You can slice the last item off of that array to get the parent object. That will contain your sibling field with the reference.
Thank you. Yes, the path prop does the trick!

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?