navigate

Programmatically navigate to routes with dynamic parameters, query strings, and history control.

API

function navigate(
  pattern: string,
  params?: Record<string, string>,
  query?: Record<string, string>,
  opts?: { replace?: boolean }
): void

Basic Usage

Use navigate to trigger navigation from event handlers, effects, or anywhere in your application logic.

import { navigate } from "@hellajs/router";

// Navigate to a static path
navigate("/dashboard");

// Substitute route parameters
// Navigates to /posts/hello-world
navigate("/posts/:slug", { slug: "hello-world" });

// Add query parameters
// Navigates to /search?q=reactive
navigate("/search", {}, { q: "reactive" });

Key Concepts

History Management

navigate integrates with the browser’s History API, pushing new entries by default or replacing them with the replace option.

// Adds new history entry (user can go back)
navigate('/dashboard');

// Replaces current history entry (user cannot go back)
navigate('/dashboard', {}, {}, { replace: true });

Parameter Substitution

Route patterns with :param placeholders use simple string replacement with automatic URL encoding. Understanding the exact behavior prevents navigation errors.

// Parameter substitution uses string.replace() with URL encoding
navigate('/users/:id/posts/:postId', {
  id: '123',
  postId: 'hello-world'
}); // Results in: /users/123/posts/hello-world

// Special characters are automatically URL-encoded
navigate('/search/:term', {
  term: 'hello world & more!'
}); // Results in: /search/hello%20world%20%26%20more!

// Unused parameters are ignored silently
navigate('/users/:id', {
  id: '123',
  unusedParam: 'ignored' // This parameter is ignored
}); // Results in: /users/123

// Unmatched :param patterns are removed from URL
navigate('/users/:id/posts/:postId', {
  id: '123'
  // Missing postId parameter
}); // Results in: /users/123/posts/ (clean URL with removed param)

// Option 2: Using final URL directly (no substitution needed)
navigate('/users/123/posts/hello-world');

Important Parameter Behavior:

  • Parameters are URL-encoded automatically
  • Unused parameters are ignored (no error thrown)
  • Missing parameters are removed from URL (:param patterns cleaned)
  • Parameter keys must exactly match the pattern placeholder names

Query String Handling

Query parameters are automatically serialized with URL encoding and appended to the final URL.

navigate('/search', {}, { 
  q: 'reactive', 
  category: 'frameworks',
  page: '2' 
}); // Results in: /search?q=reactive&category=frameworks&page=2

// Special characters in query values are URL-encoded
navigate('/search', {}, {
  q: 'hello world & more',
  filter: 'type=advanced'
}); // Results in: /search?q=hello%20world%20%26%20more&filter=type%3Dadvanced

// Empty query object results in no query string
navigate('/search', {}, {}); // Results in: /search

// Undefined/null query values are converted to strings
navigate('/search', {}, {
  q: undefined,
  page: null
}); // Results in: /search?q=undefined&page=null

Important Considerations

Asynchronous Navigation

Navigation is asynchronous - the route change isn’t immediate.

// ❌ Route may not be updated yet
navigate('/dashboard');
console.log(route().path);
// ✅ Use effect for route changes
effect(() => {
  if (route().path === '/dashboard') {
    console.log('Dashboard loaded');
  }
});

Replace vs Push

Using replace: true prevents users from navigating back to the previous page.

// ✅ Normal navigation - can go back
navigate('/new-page');
// ✅ Replace - overwrites history entry
navigate('/redirect', {}, {}, { replace: true });

Parameter Validation

The router performs no parameter validation - invalid keys are silently ignored and missing keys create malformed URLs.

// ✅ Correct parameter key
navigate('/users/:id', { id: '123' });
// Results in: /users/123

// ❌ Wrong key, param not substituted - gets removed
navigate('/users/:id', { userId: '123' });
// Results in: /users/ (param removed, likely unintended route)

// ❌ Missing required parameter - param gets removed
navigate('/users/:id/posts/:postId', { id: '123' });
// Results in: /users/123/posts/ (param removed, may not match intended route)

// ✅ Best practice: validate parameters before navigation
const navigateToUser = (userId) => {
  if (!userId) {
    console.error('User ID is required');
    return;
  }
  navigate('/users/:id', { id: userId });
};

Parameter Validation Recommendations:

  • Always validate parameters before calling navigate()
  • Use TypeScript for compile-time parameter checking
  • Consider using helper functions for common navigation patterns
  • Test navigation with missing/invalid parameters during development