Skip to main content
useNavigate is a React hook that provides programmatic navigation within your AppShell application. It’s re-exported from react-router v7 and is essential for navigating between pages in response to user actions.
Always import useNavigate from @tailor-platform/app-shell, not from react-router directly. AppShell manages its own router instance, and importing from the wrong package will cause navigation to fail.

Usage

import { useNavigate } from '@tailor-platform/app-shell';

const MyComponent = () => {
  const navigate = useNavigate();

  const handleClick = () => {
    // Navigate to a route
    navigate('/dashboard/overview');
  };

  return <button onClick={handleClick}>Go to Dashboard</button>;
};

Signature

const navigate: NavigateFunction = useNavigate();

type NavigateFunction = (
  to: string | number,
  options?: NavigateOptions
) => void;

interface NavigateOptions {
  replace?: boolean;      // Replace current entry in history
  state?: any;           // Pass state to the new location
  preventScrollReset?: boolean;  // Prevent scroll reset on navigation
  relative?: 'route' | 'path';   // Relative path resolution strategy
}

Examples

Basic Navigation

import { useNavigate } from '@tailor-platform/app-shell';

const ProductList = () => {
  const navigate = useNavigate();

  const viewProduct = (productId: string) => {
    navigate(`/products/${productId}`);
  };

  return (
    <div>
      <button onClick={() => viewProduct('123')}>View Product</button>
    </div>
  );
};
Use replace: true to replace the current history entry instead of adding a new one:
const LoginPage = () => {
  const navigate = useNavigate();

  const handleLogin = async (credentials) => {
    await loginUser(credentials);
    // Replace login page in history so back button doesn't return to login
    navigate('/dashboard', { replace: true });
  };

  return <LoginForm onSubmit={handleLogin} />;
};
Pass data to the destination route using the state option:
import { useNavigate, useLocation } from '@tailor-platform/app-shell';

// Source component
const OrderList = () => {
  const navigate = useNavigate();

  const createOrder = () => {
    navigate('/orders/new', {
      state: { from: 'order-list', timestamp: Date.now() }
    });
  };

  return <button onClick={createOrder}>Create Order</button>;
};

// Destination component
const NewOrderPage = () => {
  const location = useLocation();
  const { from, timestamp } = location.state || {};

  return (
    <div>
      <h1>New Order</h1>
      {from && <p>Navigated from: {from}</p>}
    </div>
  );
};
Use negative numbers to navigate backward in history:
const ProductDetail = () => {
  const navigate = useNavigate();

  return (
    <div>
      <button onClick={() => navigate(-1)}>← Back</button>
      <h1>Product Details</h1>
    </div>
  );
};

Dynamic Routes with Params

import { useNavigate, useParams } from '@tailor-platform/app-shell';

const OrderDetail = () => {
  const navigate = useNavigate();
  const { id } = useParams();

  const goToEditPage = () => {
    navigate(`/orders/${id}/edit`);
  };

  return (
    <div>
      <h1>Order {id}</h1>
      <button onClick={goToEditPage}>Edit Order</button>
    </div>
  );
};

Type-Safe Navigation with Generated Routes

When using file-based routing with the Vite plugin, you can generate type-safe route helpers:
import { useNavigate } from '@tailor-platform/app-shell';
import { paths } from './routes.generated';

const MyComponent = () => {
  const navigate = useNavigate();

  // ✅ Type-checked path and params
  const goToOrder = (orderId: string) => {
    navigate(paths.for('/orders/:id', { id: orderId }));
  };

  // ✅ Static routes
  const goToDashboard = () => {
    navigate(paths.for('/dashboard'));
  };

  return (
    <div>
      <button onClick={() => goToOrder('123')}>View Order</button>
      <button onClick={goToDashboard}>Dashboard</button>
    </div>
  );
};
See Type-Safe Navigation for setup instructions.

Common Patterns

Conditional Navigation

const handleSubmit = async (formData) => {
  const result = await saveData(formData);
  
  if (result.success) {
    navigate('/success');
  } else {
    navigate('/error', { state: { error: result.error } });
  }
};
const DeleteButton = ({ itemId }) => {
  const navigate = useNavigate();

  const handleDelete = async () => {
    if (window.confirm('Are you sure?')) {
      await deleteItem(itemId);
      navigate('/items');
    }
  };

  return <button onClick={handleDelete}>Delete</button>;
};
Use CaseUse
User clicks a link or button<Link to="/path">
Navigate after form submissionnavigate('/path')
Navigate after API callnavigate('/path')
Conditional navigation based on logicnavigate('/path')
Navigate backwardnavigate(-1)

See Also

Build docs developers (and LLMs) love