Skip to content
Twilight React Playground
ثيم رائدaren

useLocation

hookBeginnerserverbrowserlive demo

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

The current address as the router sees it: path, parsed query, raw query and hash. It works in the server render too.Try this: set the value to 2 and navigate: search holds the number 2, not the text "2". If the readout lags, press Read again.
Storefront canvas · en · LTR

search.sort (undefined)

useLocation(): {…} 8 keys
href: "/en/playground/reference/core/use-location"
pathname: "/en/playground/reference/core/use-location"
search: {}
searchStr: ""
state: {…} 3 keys
key: "ptoi2g"
__TSR_key: "ptoi2g"
__TSR_index: 0
hash: ""
publicHref: "/en/playground/reference/core/use-location"
external: false
Controls
What a theme writes
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

app/components/NextPageButton.tsx
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 beforeLoad writes 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.

  • pathname is 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 to navigate().

  • The same value is useTwilight().location, and getTwilightContext().location from /tanstack outside React.

Gotchas

  • search values are JSON-parsed by TanStack Router's default parseSearch: ?page=2 gives the number 2, ?gift=true the boolean true, and only text that is not JSON stays a string. Compare with String(search.page), or read searchStr. The engine's docblock and packages/theme-engine/docs/useLocation.md show page: '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 outside TwilightProvider. docs/16-client-navigation.md describes the result as { pathname, search: string, fullPath }: there is no fullPath, and search is an object.

Related

Source and docs