Documentation Index
Fetch the complete documentation index at: https://mintlify.com/tighten/ziggy/llms.txt
Use this file to discover all available pages before exploring further.
The useRoute() hook provides the route() function for React components, enabling URL generation from Laravel route names with automatic configuration handling.
Hook Signature
function useRoute(defaultConfig?: Config): typeof route;
Parameters
Optional Ziggy configuration object to use as the default for all route calls. If not provided, the hook will attempt to use the global Ziggy variable or load config from a #ziggy-routes-json script tag.Required if:
- No global
Ziggy variable is defined
- No
#ziggy-routes-json script tag exists
- Running in a non-browser environment (SSR, tests)
Properties:
url: Application URL
port: Application port (or null)
defaults: Default parameter values
routes: Route definitions object
location: Override current location (for SSR)
Return Value
Returns a configured route() function that can be called with:
(name, params?, absolute?, config?) to generate a URL string
() with no arguments to return a Router instance
The returned function signature:
(name?: string, params?: RouteParams, absolute?: boolean, config?: Config) => string | Router
Basic Usage
import { useRoute } from 'ziggy-js';
function PostsList() {
const route = useRoute();
return (
<div>
<a href={route('posts.index')}>All Posts</a>
<a href={route('posts.create')}>New Post</a>
</div>
);
}
Usage with Parameters
import { useRoute } from 'ziggy-js';
function Post({ post }) {
const route = useRoute();
return (
<article>
<h1>{post.title}</h1>
<div>
<a href={route('posts.show', post.id)}>View</a>
<a href={route('posts.edit', post.id)}>Edit</a>
<button onClick={() => deletePost(post.id)}>Delete</button>
</div>
</article>
);
function deletePost(id) {
fetch(route('posts.destroy', id), { method: 'DELETE' })
.then(() => window.location.reload());
}
}
Usage with Custom Configuration
import { useRoute } from 'ziggy-js';
import Ziggy from './ziggy';
function App() {
// Pass custom Ziggy configuration
const route = useRoute(Ziggy);
return (
<nav>
<a href={route('home')}>Home</a>
<a href={route('about')}>About</a>
</nav>
);
}
Advanced Examples
Multiple Parameters
import { useRoute } from 'ziggy-js';
function Comment({ comment }) {
const route = useRoute();
return (
<div>
{/* Array of parameters */}
<a href={route('posts.comments.show', [comment.post_id, comment.id])}>
View Comment
</a>
{/* Named parameters */}
<a href={route('posts.comments.show', {
post: comment.post_id,
comment: comment.id
})}>
View Comment
</a>
</div>
);
}
Query Parameters
import { useRoute } from 'ziggy-js';
function PostsIndex({ page, filters }) {
const route = useRoute();
return (
<div>
<a href={route('posts.index', { _query: { page: page + 1 } })}>
Next Page
</a>
<a href={route('posts.index', {
_query: {
filter: filters,
sort: 'recent'
}
})}>
Filter Posts
</a>
</div>
);
}
Relative URLs
import { useRoute } from 'ziggy-js';
import { useNavigate } from 'react-router-dom';
function Navigation() {
const route = useRoute();
const navigate = useNavigate();
const handleClick = (e) => {
e.preventDefault();
// Generate relative path for client-side routing
const path = route('posts.index', null, false);
navigate(path);
};
return (
<a href={route('posts.index')} onClick={handleClick}>
Posts
</a>
);
}
Current Route Checking
import { useRoute } from 'ziggy-js';
function Navigation() {
const route = useRoute();
// Get router instance to check current route
const router = route();
return (
<nav>
<a
href={route('posts.index')}
className={router.current('posts.*') ? 'active' : ''}
>
Posts
</a>
<a
href={route('about')}
className={router.current('about') ? 'active' : ''}
>
About
</a>
</nav>
);
}
Route Existence Check
import { useRoute } from 'ziggy-js';
function AdminPanel() {
const route = useRoute();
const router = route();
if (!router.has('admin.dashboard')) {
return null; // Hide admin panel if routes don't exist
}
return (
<div>
<a href={route('admin.dashboard')}>Dashboard</a>
<a href={route('admin.users')}>Users</a>
</div>
);
}
Accessing Current Route Parameters
import { useRoute } from 'ziggy-js';
import { useEffect, useState } from 'react';
function PostPage() {
const route = useRoute();
const [post, setPost] = useState(null);
useEffect(() => {
// Get current route parameters
const { post: postId } = route().params;
// Fetch the post
fetch(route('api.posts.show', postId))
.then(res => res.json())
.then(setPost);
}, []);
return post ? <div>{post.title}</div> : <div>Loading...</div>;
}
Error Handling
The useRoute() hook throws an error if no configuration is available:
import { useRoute } from 'ziggy-js';
import { ErrorBoundary } from 'react-error-boundary';
function App() {
return (
<ErrorBoundary
fallback={<div>Configuration error</div>}
onError={(error) => {
console.error('Ziggy error:', error.message);
}}
>
<PostsList />
</ErrorBoundary>
);
}
function PostsList() {
try {
const route = useRoute();
return <a href={route('posts.index')}>Posts</a>;
} catch (error) {
// Error: Ziggy error: missing configuration. Ensure that a `Ziggy`
// variable is defined globally or pass a config object into the useRoute hook.
return <div>Unable to load routes</div>;
}
}
To prevent errors, always provide configuration when no global Ziggy variable exists:
import { useRoute } from 'ziggy-js';
import ziggyConfig from './ziggy';
function App() {
// Pass config to prevent errors
const route = useRoute(ziggyConfig);
return <a href={route('posts.index')}>Posts</a>;
}
Server-Side Rendering (SSR)
For SSR with frameworks like Next.js or Remix, provide configuration with a custom location:
Next.js App Router
import { useRoute } from 'ziggy-js';
function PostsList({ ziggyConfig }) {
const route = useRoute(ziggyConfig);
return (
<div>
<a href={route('posts.index')}>Posts</a>
</div>
);
}
export async function generateMetadata({ params }) {
// Pass Ziggy config from server
return {
title: 'Posts'
};
}
Next.js Pages Router
import { useRoute } from 'ziggy-js';
function Page({ ziggy }) {
const route = useRoute(ziggy);
return <a href={route('posts.index')}>Posts</a>;
}
export async function getServerSideProps({ req }) {
return {
props: {
ziggy: {
...Ziggy,
location: {
host: req.headers.host,
pathname: req.url,
search: ''
}
}
}
};
}
export default Page;
TypeScript Support
The hook is fully typed for TypeScript:
import { useRoute } from 'ziggy-js';
import type { Config, RouteUrl } from 'ziggy-js';
function PostsList() {
const route = useRoute();
// Return type is RouteUrl (branded string)
const url: RouteUrl = route('posts.show', 1);
// TypeScript validates route names and parameters
route('posts.show', { post: 1 }); // ✓
route('posts.show', { invalid: 1 }); // ✗ Type error
return <a href={url}>Post</a>;
}
With custom configuration:
import { useRoute } from 'ziggy-js';
import type { Config } from 'ziggy-js';
import ziggyConfig from './ziggy';
function App() {
const config: Config = ziggyConfig;
const route = useRoute(config);
return <a href={route('home')}>Home</a>;
}
Implementation Details
The useRoute() hook performs configuration validation and returns a configured route function:
export function useRoute(defaultConfig) {
// Validate configuration availability
if (
!defaultConfig &&
!globalThis.Ziggy &&
typeof Ziggy === 'undefined' &&
!document.getElementById('ziggy-routes-json')
) {
throw new Error(
'Ziggy error: missing configuration. Ensure that a `Ziggy` variable is defined globally or pass a config object into the useRoute hook.',
);
}
// Return configured route function
return (name, params, absolute, config = defaultConfig) =>
route(name, params, absolute, config);
}
The hook:
- Validates that configuration is available from at least one source
- Returns a closure that wraps the
route() function
- Uses
defaultConfig as the fallback for the config parameter
Configuration Precedence
Configuration is used in this order (highest to lowest priority):
- Per-call config:
route('posts.show', 1, true, customConfig)
- Hook config:
useRoute(defaultConfig)
- Global
Ziggy variable: window.Ziggy or globalThis.Ziggy
- Script tag:
<script id="ziggy-routes-json">...</script>
Best Practices
// hooks/useZiggy.js
import { useRoute } from 'ziggy-js';
import ziggyConfig from '../ziggy';
export function useZiggy() {
return useRoute(ziggyConfig);
}
// Usage in components
import { useZiggy } from './hooks/useZiggy';
function MyComponent() {
const route = useZiggy();
return <a href={route('posts.index')}>Posts</a>;
}
Context Provider Pattern
import { createContext, useContext } from 'react';
import { useRoute } from 'ziggy-js';
const RouteContext = createContext(null);
export function RouteProvider({ config, children }) {
const route = useRoute(config);
return (
<RouteContext.Provider value={route}>
{children}
</RouteContext.Provider>
);
}
export function useZiggy() {
const route = useContext(RouteContext);
if (!route) {
throw new Error('useZiggy must be used within RouteProvider');
}
return route;
}
// Usage
function App() {
return (
<RouteProvider config={ziggyConfig}>
<PostsList />
</RouteProvider>
);
}
function PostsList() {
const route = useZiggy();
return <a href={route('posts.index')}>Posts</a>;
}
See Also