How to get Sanity client instance in custom tool component?

2 replies
Last updated: Sep 25, 2023
Hi there, I've looked already at many threads mentioning custom tools, but I still failed to understand how to get a sanity client instance. I created a function that returns a tool definition:
import { UnpublishIcon } from '@sanity/icons'
import { Card, Text } from '@sanity/ui'

const xlsxImport = () => {

    return {
        title: 'XLSX Importer',
        name: 'xlsx-import', // localhost:3333/my-custom-tool
        icon: UnpublishIcon,
        component: (props: any, other:any) => {
            console.log(props, other)
            return <Card padding={4} >
                <Text>Import XLSX</ Text >
            </Card>
        },
    }
}

export default xlsxImport
and added the tool in my
sanity.config.ts
:
export default defineConfig({
  basePath: '/studio',
  projectId,
  dataset,
  schema,
  plugins: [
    deskTool({
      structure: myStructure
    }),
    visionTool({defaultApiVersion: apiVersion}),
  ],
  tools: [
    xlsxImport()
  ]
})
I can see my tool in sanity studio, but how do I get a configured client in my tool so I can make changes? I read
https://www.sanity.io/docs/tool-api-reference#91832d1f6f69 (Tool Context Properties) and there is a mention of a "getClient" function, but I don't know where to call that. Can anyone help me out?
AI Update

Perfect! The answer is straightforward - you need to use the useClient hook inside your React component. Since useClient is a React hook, it must be called inside your component function, not at the top level of your tool definition.

Here's how to modify your code:

import { UnpublishIcon } from '@sanity/icons'
import { Card, Text } from '@sanity/ui'
import { useClient } from 'sanity'

const xlsxImport = () => {
    return {
        title: 'XLSX Importer',
        name: 'xlsx-import',
        icon: UnpublishIcon,
        component: (props) => {
            // Call useClient here, inside the React component
            const client = useClient({ apiVersion: '2024-01-01' })
            
            // Now you can use the client for operations
            const handleImport = async () => {
                // Example: create a document
                await client.create({
                    _type: 'yourDocumentType',
                    // ... your data
                })
                
                // Or fetch data
                const data = await client.fetch('*[_type == "yourType"]')
            }
            
            return (
                <Card padding={4}>
                    <Text>Import XLSX</Text>
                </Card>
            )
        },
    }
}

export default xlsxImport

The key points from the useClient documentation:

  1. Import the hook: import { useClient } from 'sanity'
  2. Call it inside your component: Since it's a React hook, it must be called inside the component function (following React's Rules of Hooks)
  3. Specify an API version: Pass an object with the apiVersion you want to use

The getClient mentioned in the Tool Context Properties is a different approach that was more common in Studio v2. In Studio v3, the recommended pattern is to use the useClient hook directly in your component, which gives you a configured client instance that's already set up with your project ID, dataset, and authentication.

If you need to perform operations that the basic client doesn't cover, you can also access specialized features like AI Agent Actions through the client instance (e.g., client.agent.action.generate()).

Show original thread
2 replies
omg, that's so simple. I guess that should be in the Tool documentation.Thanks a lot
user P
!

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?