useLocation
Reads the current address as the router sees it (path, parsed query, raw query, hash), in the server render and in the browser.
import { useLocation, Location } from '@salla.sa/twilight-theme-engine/providers';In plain words
window.location does not exist while the server builds a page, and on some hosts the address bar holds more than the path your theme works with. useLocation() gives you the address as the router sees it: pathname, search (the query already turned into an object), searchStr (the raw ?… text), hash and href.
Use it to highlight the active filter, read ?page=, or build a link back to the page you are on.
Signature
function useLocation<TSearch = Record<string, unknown>>(): Location<TSearch>
interface Location<TSearch> { // TwilightLocation
href: string;
pathname: string; // '/ar/search'
search: TSearch; // { q: 'oud', page: 2 }
searchStr: string; // '?q=oud&page=2'
hash: string;
state: Record<string, unknown>;
}Try it live
search.sort → (undefined)
useLocation(): {…} 8 keys
state: {…} 3 keys
import { useLocation, useNavigate } from '@salla.sa/twilight-theme-engine/providers';
export function FilterButton() {
const { pathname, search } = useLocation<{ sort?: string | number }>();
const navigate = useNavigate();
// Query values are JSON-parsed: ?page=2 gives the number 2. Compare as strings.
const active = String(search.sort) === 'price-asc';
return (
<button
type="button"
aria-pressed={active}
onClick={() => navigate(`${pathname}?sort=price-asc`)}
>
sort: price-asc
</button>
);
}
Example
import { useLocation, useNavigate } from '@salla.sa/twilight-theme-engine/providers';
export function NextPageButton() {
const { pathname, search } = useLocation<{ page?: number }>();
const navigate = useNavigate();
const page = Number(search.page ?? 1);
return (
<button type="button" onClick={() => navigate(`${pathname}?page=${page + 1}`)}>
Page {page + 1}
</button>
);
}
How it behaves
The root route's
beforeLoadwrites the location into the request context on every navigation, and the router writes it again when navigation resolves. The hook reads that value on render.pathnameis the application path, locale included, without the store segment localhost and the preview host show in the address bar. It is safe to hand back tonavigate().The same value is
useTwilight().location, andgetTwilightContext().locationfrom/tanstackoutside React.
Gotchas
searchvalues are JSON-parsed by TanStack Router's defaultparseSearch:?page=2gives the number2,?gift=truethe booleantrue, and only text that is not JSON stays a string. Compare withString(search.page), or readsearchStr. The engine's docblock and packages/theme-engine/docs/useLocation.md showpage: '2'.It does not subscribe to navigation, unlike
useRouteId(): it returns what the context held when the component rendered. Route components render again on navigation, but a memoized component outside the route can keep an old value.It calls
useTwilight(), so it throws outsideTwilightProvider. docs/16-client-navigation.md describes the result as{ pathname, search: string, fullPath }: there is nofullPath, andsearchis an object.