Understanding useRouter and usePaneRouter hooks in Sanity v3

4 replies
Last updated: Jul 17, 2023
Hey peeps I'm struggling to find information on the 'useRouter','usePaneRouter' and/or hooks, I think I need them to navigate a user programmatically to a new document. There are few old chats here discussing this, but all seem to relate to v2?
AI Update

I understand the frustration - documentation on programmatic navigation in Sanity Studio v3 is indeed sparse, and you're right that most of the older discussions relate to v2 which had different APIs.

Unfortunately, there isn't official documentation for useRouter or usePaneRouter hooks in Studio v3. These hooks may exist in the codebase (you might see them referenced in community discussions), but they're not part of the documented public API, which makes them risky to rely on since they could change without notice.

What's Actually Documented

Based on the current official documentation, here are the approaches that are supported:

1. Intent Handling with canHandleIntent

If you're building custom Structure Builder components, you can use the intent handling system. This allows custom components to respond to navigation requests (like when someone clicks a search result or follows a link):

S.listItem()
  .id('my-custom-view')
  .title('My Custom View')
  .child(
    S.component(MyComponent)
      .id('example')
      .canHandleIntent((intent, params, context) => {
        // intent: 'create' or 'edit'
        // params: { type, id, template }
        // context: additional info
        console.log(intent, params, context)
        return true // return true if this component can handle the intent
      })
  )

However, this is about receiving navigation requests, not initiating them programmatically from your code.

2. App SDK (for External Apps)

If you're building a custom app outside of Studio (not a Studio plugin), the App SDK provides hooks like useNavigateToStudioDocument that can generate links to navigate from your app to Studio documents. But this is specifically for external apps bridging to Studio, not for navigation within Studio itself.

The Documentation Gap

You've identified a real gap in the documentation. The ability to programmatically navigate within Studio v3 from custom plugins or components isn't well-documented. This is a common pain point for developers building custom Studio experiences.

What You Can Do

For now, your options are:

  1. Use declarative approaches where possible - Structure Builder configurations, intent links, etc.
  2. Post in the Sanity Slack community - The team and community are usually responsive about clarifying undocumented APIs or providing workarounds
  3. Check the TypeScript types - If you're using TypeScript, you might find some hints about available hooks by exploring the type definitions in node_modules/sanity
  4. Consider if your use case could be solved differently - Sometimes restructuring with the Structure Builder can achieve similar results without programmatic navigation

I wish I had a more complete answer, but the documentation genuinely doesn't cover this use case thoroughly in v3. You're not missing something obvious - it's just not publicly documented yet!

Show original thread
4 replies
👋 We don’t have that documented for V3, but here’s an example from a previous thread:
import {definePlugin} from 'sanity'
import {route, useRouter} from 'sanity/router'
import {useEffect} from 'react'
import {Box, Button} from '@sanity/ui'

const PATHS = ['view-1', 'view-2']

function MyTool() {
  const router = useRouter()

  // Set the default path if no path is set or if the path is not valid
  useEffect(() => {
    if (!PATHS.includes(router.state.path as string)) {
      router.navigate({path: PATHS[0]})
    }
  }, [router])

  return (
    <div>
      {PATHS.map((path) => (
        <Button
          key={path}
          mode="ghost"
          onClick={() => router.navigate({path})}
          selected={router.state.path === path}
          text={path}
        />
      ))}

      <Box padding={4}>
        {router.state.path === PATHS[0] && <div>View 1</div>}
        {router.state.path === PATHS[1] && <div>View 2</div>}
      </Box>
    </div>
  )
}

export const toolWithRouting = definePlugin({
  name: 'my-tool',
  tools: [
    {
      component: MyTool,
      name: 'my-tool',
      router: route.create('/', [route.create('/:path')]),
      title: 'Tool',
    },
  ],
})
Thanks for the speedy reply, I'll take what you've provided and see how far I get 🙏
let us know if you need more help with implementation.

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?