Help needed with building a nested category system in JavaScript
In Sanity Studio v3, accessing validation rules in custom input components works differently than in v2. The internal _rules structure you used in v2 is no longer directly accessible in the same way.
In v3, custom input components receive their props through a different structure. Here's what you need to know:
The v3 Approach
Your custom input component receives a schemaType prop that contains schema information about the field. While you can't directly access the internal _rules array like you could in v2, you have a couple of options:
Option 1: Access validation through schemaType
The schemaType prop contains the validation rules, though the structure is different from v2. Here's how you can work with it:
import { TextInput, Stack, Text } from '@sanity/ui'
import { set, unset } from 'sanity'
export const MyCustomInput = (props) => {
const { elementProps, onChange, value = '', schemaType } = props
// Access validation from schemaType
const validation = schemaType.validation
// You can inspect the validation rules
// Note: The structure is different from v2's _rules
let maxConstraint = null
if (validation && Array.isArray(validation)) {
validation.forEach(rule => {
// The rule structure in v3 is different - you'll need to inspect it
// You might need to call the rule to get constraints
const ruleSpec = rule(schemaType)
// Extract max constraint from ruleSpec
})
}
const handleChange = (event) => {
const inputValue = event.currentTarget.value
onChange(inputValue ? set(inputValue) : unset())
}
return (
<Stack space={2}>
<TextInput {...elementProps} onChange={handleChange} value={value} />
<Text muted size={1}>
{value ? value.length : '0'} {maxConstraint && `/ ${maxConstraint}`}
</Text>
</Stack>
)
}Option 2: The Recommended Approach - Define constraints explicitly
Rather than trying to extract validation rules from the schema, the v3 approach encourages you to be more explicit. If you need a max constraint in your custom component, pass it as an option:
// In your schema
defineField({
name: 'title',
type: 'string',
validation: Rule => Rule.max(100),
components: {
input: MyCustomInput
},
options: {
maxLength: 100 // Explicitly pass the constraint
}
})Then access it via schemaType.options:
export const MyCustomInput = (props) => {
const { elementProps, onChange, value = '', schemaType } = props
const maxLength = schemaType.options?.maxLength
// Now you can use maxLength in your component
return (
<Stack space={2}>
<TextInput {...elementProps} onChange={handleChange} value={value} />
<Text muted size={1}>
{value ? value.length : '0'} {maxLength && `/ ${maxLength}`}
</Text>
</Stack>
)
}Why the change?
In v3, Sanity moved away from exposing internal implementation details like _rules. The validation system is more abstracted now, which makes it more flexible but also means you can't peek into its internals the same way.
The options approach is cleaner and more maintainable - you're being explicit about what your custom component needs rather than relying on parsing internal validation structures.
If you absolutely need to extract validation constraints programmatically, you may need to inspect the schemaType.validation array more carefully, but be aware this is working against the grain of v3's design philosophy and may be fragile across updates.
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.