🔮 Sanity Create is here. Writing is reinvented. Try now, no developer setup

Custom Input: Recreated String Field Starter

By Bryan Robinson

This is a starting point for the creation of a custom string input. It recreates the basic functionality of the default string input.


// /src/MyCustomString.js

import React from 'react'
import { FormField } from '@sanity/base/components'
import { TextInput } from '@sanity/ui'
import PatchEvent, {set, unset} from '@sanity/form-builder/PatchEvent'
// be sure to npm install @reach/auto-id
import { useId } from "@reach/auto-id" // hook to generate unique IDs

const MyCustomString = React.forwardRef((props, ref) => {
    const { 
            type,         // Schema information
            value,        // Current field value
            readOnly,     // Boolean if field is not editable
            placeholder,  // Placeholder text from the schema
            markers,      // Markers including validation rules
            presence,     // Presence information for collaborative avatars
            compareValue, // Value to check for "edited" functionality
            onFocus,      // Method to handle focus state
            onBlur,       // Method to handle blur state  
            onChange      // Method to handle patch events
          } = props

    // Creates a unique ID for our input
    const inputId = useId()

    // Creates a change handler for patching data
    const handleChange = React.useCallback(
      // useCallback will help with performance
      (event) => {
        const inputValue = event.currentTarget.value // get current value
        // if the value exists, set the data, if not, unset the data
        onChange(PatchEvent.from(inputValue ? set(inputValue) : unset()))

    return (
        description={type.description}  // Creates description from schema
        title={type.title}              // Creates label from schema title
        __unstable_markers={markers}    // Handles all markers including validation
        __unstable_presence={presence}  // Handles presence avatars
        compareValue={compareValue}     // Handles "edited" status
        inputId={inputId}               // Allows the label to connect to the input field
          id={inputId}                  // A unique ID for this input
          onChange={handleChange}       // A function to call when the input value changes
          value={value}                 // Current field value
          readOnly={readOnly}           // If "readOnly" is defined make this field read only
          placeholder={placeholder}     // If placeholder is defined, display placeholder text
          onFocus={onFocus}             // Handles focus events
          onBlur={onBlur}               // Handles blur events

// Create the default export to import into our schema
export default MyCustomString


import MyCustomString from '../src/MyCustomString'

export default {
  name: 'aDocument',
  title: 'A regular document',
  type: 'document',
  fields: [
      name: 'simple',
      title: 'Simple String',
      type: 'string',
      inputComponent: MyCustomString

This snippet is a "jumping-off point" for the creation of custom string inputs. It re-implements all of the functionality of a default string type input and can be used to create a more detailed or customized string input.

The full walk-through for recreating this can be found in the official docs for Custom Inputs.


Other schemas by author