Search
The search string of a url is the part after the question mark ?
and consists of key-value pairs, called "search parameters" separated by &
symbols.
It allows you to add extra parameters to a url.
The search and searchParams are available in route components as attributes of the location
URL.
function Route() {
let location = useLocation()
let search = location.search
let searchParams = location.searchParams
...
}
SearchParams is an instance of URLSearchParams, so take a look at this native web platform api if you are not familiar.
Loaders with search parameters
Search parameters that are not specified in the route path will not be available in the loader!
Routes that load data based on search params need to specify the search parameters they depend on. To specify search parameters for route components, the same search string syntax as for urls is used in the routes configuration:
let Router = Routes(
<App path="app">
<Todos path="todos?filter" loader={todosLoader} />
</App>,
);
function todosLoader({ url }) {
let filter = url.searchParams.get('filter');
...
}
Or if the route needs multiple search parameters:
let Router = Routes(
<App>
<Todos path="todos?order&filter" loader={todosLoader} />
</App>,
);
If you really need access to all search parameters in the loader, do not specify any specific search parameters at all.
let Router = Routes(
<App>
<Todos path="todos?" loader={todosLoader} />
</App>,
);
Using all search parameters in a route component should be avoided as much as
possible. Only use this if you do not know the names of your parameters in
advance. Explicitely stating the search parameters of your route like
/todos?order&filter
is always preferred to using the general /todos?
.
The requirement to specify the search parameters dependencies explicitely in the routes configuration allows the router to optimize data loading.
let Router = Routes(
<App path="app?language" loader={appLoader}>
<Todos path="todos?filter" loader={todosLoader} />
</App>,
)
When the url changes from /app/todos?language=fr&filter=today
to /app/todos?language=en&filter=today
only the language
search parameter has changed.
The App
route depends on the value of the language
search parameter, and its data will have to be reloaded.
The Todos
route however does not depend on the value of the language
search parameter, and its data will not have to be reloaded.
Skipping these unneeded data reloads yields substantial page load improvements.
This explains why using a path like todos?
is not recommended. The data of this route has to be reloaded with every search parameter change,
even if the search parameter was irrelevant for the loader of the route.
Matching with search parameters
Search parameters can also take part in the matching strategy of the routes.
Specifying search parameters with assigned values will only match the corresponding route if the url also has the same search parameter with that value.
let Router = Routes(
<App path="app">
<Todos path="todos?filter" />
<Today path="todos?filter=today" />
<Tomorrow path="todos?filter=tomorrow" />
</App>,
);
If the url is /app/todos
or /app/todos?filter=something
the router will render the Todos
route. If the url is /app/todos?filter=today
the router will render the Today
route, and a url /app/todos?filter=tomorrow
will render the Tomorrow
route component.
The search parameter value can also be omitted if you want to allow any value, matching only when the search parameter is present, whatever its value.
let Router = Routes(
<App path="app">
<Todos path="todos" />
<FilteredTodos path="todos?filter=" />
</App>,
);
When the filter
search parameter is present, it will render the FilteredTodos
route. If not, the Todos
route wil be rendered.