Understanding custom input components for complex objects in Sanity.io
Great question! Yes, you can absolutely pass an object to set() when working with object-type fields, and Sanity will map the keys to the field names in your schema automatically.
For your productInfo object, here's how to handle it in Studio v3 (the API has changed from v2):
import {set, unset} from 'sanity'
export const MyCustomInput = (props) => {
const {onChange, value} = props
const handleProductSelect = (selectedProduct) => {
const productData = {
productId: selectedProduct.productId,
storageId: selectedProduct.storageId,
hasAttributes: selectedProduct.hasAttributes
}
// Pass the object directly to set(), then to onChange
onChange(productData ? set(productData) : unset())
}
// ... rest of your component with dropdown, etc.
}The key difference from the docs example you referenced is that you're passing an entire object instead of a single value. The keys in your object (productId, storageId, hasAttributes) will automatically map to the corresponding field names in your productInfo schema.
Here's a complete example with a dropdown that prepopulates from your PIM:
import {useCallback} from 'react'
import {set, unset} from 'sanity'
import {Stack, Select} from '@sanity/ui'
export const ProductSelector = (props) => {
const {onChange, value} = props
// Your PIM products data
const products = [
{id: 1, name: 'Product A', productId: 90922, storageId: 29992, hasAttributes: true},
{id: 2, name: 'Product B', productId: 90923, storageId: 29993, hasAttributes: false},
// ... more products
]
const handleChange = useCallback((event) => {
const selectedId = event.currentTarget.value
if (!selectedId) {
onChange(unset())
return
}
const selectedProduct = products.find(p => p.id === parseInt(selectedId))
if (selectedProduct) {
onChange(set({
productId: selectedProduct.productId,
storageId: selectedProduct.storageId,
hasAttributes: selectedProduct.hasAttributes
}))
}
}, [onChange])
return (
<Stack space={2}>
<Select onChange={handleChange} value={value?.productId || ''}>
<option value="">Select a product</option>
{products.map(product => (
<option key={product.id} value={product.id}>
{product.name}
</option>
))}
</Select>
</Stack>
)
}Important note about Studio v3: The old PatchEvent.from() API from Studio v2 is no longer used. In v3, you import set and unset directly from sanity and pass them straight to onChange(), as shown in the official Studio v3 custom input guide.
The object you pass to set() will merge with the existing field structure, and Sanity handles all the real-time patching to the Content Lake for you!
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.