Help articles
Migration Cheat Sheet: Studio v2 to v3
Cheat sheet for migrating a Studio v2 to v3
Get a client configured with current studio's details
// In v2 import sanityClient from "part:@sanity/base/client" const client = sanityClient.withConfig({apiVersion: '2021-03-25'})
// v3 in a React component import {useClient} from 'sanity' export function MyComponent { const client = useClient({apiVersion: '2021-10-21'}) // use client as needed in, for instance in an useEffect return <div>JSX</div> } // v3 outside of React (E.g. in sanity.config.ts) import {ConfigContext, defineConfig} from 'sanity' import {structureTool, StructureBuilder} from 'sanity/structure' import {schemaTypes} from './schemas' export default defineConfig({ name: 'default', title: 'sanity-v3-structure-builder', projectId: 'your-projectId', dataset: 'your-dataset', plugins: [ structureTool({ structure: (S: StructureBuilder, context: ConfigContext) => { const {client} = context // use client to to build the structure, for instance return S.defaults() }, }), ], schema: { types: schemaTypes, }, })
If you use the same API version throughout your project, consider creating a reusable hook!
import {useMemo} from 'react' import {useClient} from 'sanity' export function useSanityClient() { const client = useClient() return useMemo(() => client.withConfig({apiVersion: '2021-10-21'}), [client]) } //use it in a component instead of useClient export function MyComponent { const client = useSanityClient() return <div>JSX</div> }
Get the current logged-in user
// In v2 // v2 code import userStore from "part:@sanity/base/user"; userStore.getCurrentUser().then((user) => { console.log(`[currentUser]:`, user ); })
// v3 inside a React component import {useCurrentUser} from 'sanity' export function MyComponent { const user = useCurrentUser() const {id, name, email, profileImage, provider, roles} = currentUser return <div>JSX</div> } // v3 outside of React, (E.g. in sanity.config.ts) import {ConfigContext, defineConfig} from 'sanity' import {structureTool, StructureBuilder} from 'sanity/structure' import {schemaTypes} from './schemas' export default defineConfig({ name: 'default', title: 'sanity-v3-structure-builder', projectId: 'your-projectId', dataset: 'your-dataset', plugins: [ structureTool({ structure: (S: StructureBuilder, context: ConfigContext) => { const {projectId, dataset, schema, currentUser, client} = context // Because `currentUser` can be null, typescript won't allow // destructuring I.e. ⬇ This won't fly! // const {id, name, email, profileImage, provider, roles} = currentUser // ...but ⬇ this will // currentUser?.id, currentUser?.name, currentUser?.email, etc... const currentProfileImage = currentUser?.profileImage ?? 'https://picsum.photos/200/300'; // your logic return S.defaults() }, }), ], schema: { types: schemaTypes, }, })
Accessing the document from your custom form component
// in v2 import {withDocument} from 'part:@sanity/form-builder' function MyInput(props) { return ( <div> Document title: {props.document.title} {/* ... */} </div> ) } export default withDocument(MyInput)
// in v3 import {useFormValue} from 'sanity' function MyInput() { const title = useFormValue([`title`]) return ( <div> Document title: {title} {/* ... */} </div> ) } export default MyInput
Accessing all document types with the schema
part
// v2 import schema from 'part:@sanity/base/schema' const namedSchema = schema.get('my-schema')
// v3 inside a React components import {useSchema} from 'sanity' export function MyComponent { const schema = useSchema() const namedSchema = schema.get('my-schema') return <div>JSX</div> } // v3 outside React (E.g. in sanity.config.ts) export default defineConfig({ name: 'default', title: 'sanity-v3-structure-builder', projectId: 'your-projectId', dataset: 'your-dataset', plugins: [ structureTool({ structure: (S: StructureBuilder, context: ConfigContext) => { const {schema} = context // use schema to look up types to build your structure return S.defaults() }, }), ], schema: { types: schemaTypes, }, })
Using config:plugin-name to configure an input component plugin
// config.dist.json { "unit": "celsius" } // src/config.js import config from 'config:plugin-name' export default { unit: config?.unit || 'celsius' } // src/schema.js export default { name: 'plugin-name.schema-type', inputComponent: Input, } // src/Input.js import config from './config' export default function Input(props) { return config.unit === 'celsius' ? <InputCelsius {...props} /> : <InputFahrenheit {...props} /> }
// src/index.tsx type Config { unit: 'celsius' | 'fahrenheit' } export const pluginName = definePlugin<Partial<Config> | void>(userConfig => { const config: Config = {unit: 'celsius', ...userConfig} return { name: 'plugin-name', form: { renderInput(props, next) { if(props.schemaType.type?.name === 'plugin-name.schema-type') { return config.unit === 'celsius' ? <InputCelsius {...props} /> : <InputFahrenheit {...props} /> } return next(props) } } } })
Custom components
// In v2 import MyCustomStarRatingComponent from '../components' export default { name: 'rating', type: 'number', title: 'How many stars?', inputComponent: MyCustomStarRatingComponent } // In v3, inside single fields import { MyCustomStarRatingInputComponent } from '../components' export default { name: 'rating', type: 'number', title: 'How many stars?', components: { input: MyCustomStarRatingInputComponent, } } // In v3, globally from the config import { MyCustomStarRatingInputComponent } from '../components' export default defineConfig({ // a lot of config form: { renderInput: (props, next) => { if (props.schemaType.name === "rating") { return MyCustomStarRatingInputComponent } return next(props) } } })
Was this page helpful?