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

dispatchRouteChanged

functionAdvancedbrowserlive demo

Fires the Salla SDK event route::changed with the current page data; the TanStack router already fires it after every navigation.

import { dispatchRouteChanged, RouteChangedEvent } from '@salla.sa/twilight-theme-engine/utils';

In plain words

Scripts outside React (analytics, chat widgets, Salla apps) need to know when the shopper moves to another page, because a storefront changes pages without reloading. After every navigation the engine sends the SDK event route::changed with the page's data: slug, title, id and so on. Anything can listen with Salla.event.on('route::changed', …).

dispatchRouteChanged() is the function that sends it. A theme listens; it rarely needs to send.

Signature

function dispatchRouteChanged(): void

type RouteChangedEvent = PageContext;
// {
//   slug: string;
//   id?: string | number;
//   title: string;
//   url?: string;
//   parent?: { id: string | number; name: string; url: string } | null;
//   breadcrumbs?: { name: string; url: string }[];
// }

Try it live

A listener on the SDK event route::changed, and a button that fires it by hand with the current page data.Try this: press the button. The payload is the last page data the router loaded: an empty object if you opened this docs page directly, the previous page (slug, title…) if you came here from a storefront page.
Storefront canvas · ar · RTL
Runs in the browser…
What a theme writes
import { useEffect } from 'react';
import { getSallaSDK, type RouteChangedEvent } from '@salla.sa/twilight-theme-engine/utils';

// The engine fires route::changed after every navigation; a theme only listens.
export function PageViewTracker() {
  useEffect(() => {
    const salla = getSallaSDK();
    if (!salla) return;
    const onRouteChanged = (...args: unknown[]) => {
      const page = args[0] as Partial<RouteChangedEvent>;
      if (!page.slug) return; // {} until a route with page data has loaded
      console.log('page view', page.slug, page.title);
    };
    salla.event.on('route::changed', onRouteChanged);
    return () => salla.event.off('route::changed', onRouteChanged);
  }, []);

  return null;
}

Example

app/components/PageViewTracker.tsx
import { useEffect } from 'react';
import { getSallaSDK, type RouteChangedEvent } from '@salla.sa/twilight-theme-engine/utils';

// The engine fires route::changed after every navigation; a theme only listens.
export function PageViewTracker() {
  useEffect(() => {
    const salla = getSallaSDK();
    if (!salla) return;
    const onRouteChanged = (...args: unknown[]) => {
      const page = args[0] as Partial<RouteChangedEvent>;
      if (!page.slug) return;
      console.log('page view', page.slug, page.title);
    };
    salla.event.on('route::changed', onRouteChanged);
    return () => salla.event.off('route::changed', onRouteChanged);
  }, []);

  return null;
}

How it behaves

  • It reads getTwilightContext().page and calls Salla.event.dispatch('route::changed', page ?? {}). It does nothing on the server, or while Salla.event.dispatch is missing.

  • createRouter() from @salla.sa/twilight-theme-engine/tanstack calls it from router.subscribe('onResolved'), after the loaders have finished and the new location is in the context. According to the engine's comment in the same file, onResolved fires only on later navigations, so the page the browser first opens is not announced this way; its page data reaches the SDK through Salla.init() instead (src/providers/twilight-init.ts).

  • The page data is the page field of the deepest route's loader data, stored by the router's onLoad subscriber, which also writes it to the SDK config as page.

Gotchas

  • Calling it yourself under TanStack sends a second event for the same navigation, so listeners such as page-view trackers count the page twice.

  • The payload is not always the current page. During client navigations the router's onLoad subscriber replaces the context's page only when the new route has page data, and never clears it, so a route without any (a 404, a custom page) sends the previous page again (src/tanstack/router.tsx). It is {} only when the page first opened had no page data and no page with data has loaded since. docs/24-route-change-events.md says 404 and error pages send {}.

  • The type marks slug and title as required, but the payload can be {}. Check before reading them.

Related

Source and docs