Queries and Params
Store state in the URL when links should preserve a page, product, or search result.
Retend provides two URL data sources: URL Parameters for route variables such as IDs, and Query Parameters for optional values such as search filters.
URL Parameters
In a dynamic route such as /users/:userId, the :userId segment is a URL Parameter. For /users/123, its value is 123.
Use the useCurrentRoute() hook to read the parameter in a component. The hook returns a reactive Cell containing the current route.
import { useCurrentRoute } from 'retend/router'; import { Cell } from 'retend'; export function UserProfile() { const currentRoute = useCurrentRoute(); // Create derived state to automatically update when the URL changes const userId = Cell.derived(() => currentRoute.get().params.get('userId')); return ( <div class="user-profile"> <h1>User Profile</h1> <p>Loading data for User ID: {userId}</p> </div> ); }
Because currentRoute is a Cell, navigating from /users/123 to /users/456 updates the userId Cell without rebuilding the component.
The route object contains:
params: AMap<string, string>of all matched URL parameters.path: The matched path pattern (e.g.,/users/:userId).fullPath: The full URL path including query string and hash.
URL data is always returned as a string. Convert it explicitly with parseInt or Number when a number is required.
Query Parameters
Query parameters are key-value pairs at the end of a URL, such as ?search=shoes&sort=price. They can represent optional values such as search terms, filters, or pagination.
Unlike URL parameters, query parameters do not need to be declared in routes. Any URL can contain them.
Reading Query Values
Use the useRouteQuery() hook to read query parameters.
import { useRouteQuery } from 'retend/router'; import { If } from 'retend'; export function SearchResults() { const query = useRouteQuery(); // Returns a Cell containing the string, or null if it doesn't exist const searchTerm = query.get('search'); // Returns a boolean Cell indicating if the parameter exists const hasFilter = query.has('category'); return ( <div class="results"> <p>You searched for: {searchTerm}</p> {If(hasFilter, { true: () => <span class="badge">Category filter applied</span>, })} </div> ); }
If a URL has multiple values for the same key (like ?tags=red&tags=blue), you can use query.getAll('tags') to get an array of all the values.
Updating Query Parameters
The query object also provides methods for updating the URL, without manually constructing a URL string.
These methods are asynchronous because updating the URL performs navigation:
import { useRouteQuery } from 'retend/router'; export function Filters() { const query = useRouteQuery(); const handleSortChange = async (event: Event) => { const target = event.target as HTMLSelectElement; // This updates the URL to include ?sort=date (for example) await query.set('sort', target.value); }; const clearAll = async () => { // This removes all query parameters from the URL await query.clear(); }; return ( <div class="filters"> <select onChange={handleSortChange}> <option value="relevance">Relevance</option> <option value="date">Date</option> <option value="price">Price</option> </select> <button type="button" onClick={clearAll}> Reset Filters </button> </div> ); }
Query parameters are reactive. Calling query.set() updates the URL and the components that read the value with query.get().