updateTwilightContext
Writes values into the current twilight context: the request's own on the server, the page's single context in the browser.
import { updateTwilightContext } from '@salla.sa/twilight-theme-engine/tanstack';In plain words
The engine keeps page-wide facts (settings, language, location, auth token) in the twilight context. The router and the root route write them as pages load, with updateTwilightContext().
A theme rarely needs it. The safe place for values of your own is extras, a field the engine stores for you and never reads itself.
Signature
function updateTwilightContext(partial: Partial<TwilightContext>): void
Try it live
updateTwilightContext({ extras }), then reads the context back. The demo restores the old value when you leave.Try this: write the campaign, then the banner: campaign is gone. extras is replaced, not merged.import {
getTwilightContext,
updateTwilightContext,
} from '@salla.sa/twilight-theme-engine/tanstack';
// In an event handler or effect, never while rendering.
export function rememberCampaign() {
const { extras } = getTwilightContext();
// extras is replaced as a whole, so spread what is already there.
updateTwilightContext({ extras: { ...extras, campaign: 'summer-sale' } });
}
Example
import { useEffect } from 'react';
import { useLocation } from '@salla.sa/twilight-theme-engine/providers';
import {
getTwilightContext,
updateTwilightContext,
} from '@salla.sa/twilight-theme-engine/tanstack';
// Remembers ?utm_campaign= for loaders that run in this browser later.
export function CampaignCapture() {
const { search } = useLocation<{ utm_campaign?: string }>();
const campaign = search.utm_campaign ? String(search.utm_campaign) : null;
useEffect(() => {
if (!campaign) return;
const { extras } = getTwilightContext();
updateTwilightContext({ extras: { ...extras, campaign } });
}, [campaign]);
return null;
}
How it behaves
queryClient,settings,locale,routeIdandi18nignorenullandundefined, so they cannot be cleared.locationis merged into the current location field by field.authToken,scope,storeId,storeBase,versionIdandrequestHostacceptnullto clear.page,appsSnippets,appsSettingsandextrasare replaced by whatever you pass,undefinedincluded.scopeIdsetsscopeto{ id }whenscopeitself is not given.In the browser it notifies subscribers, so
useRouteId()and the page-detection hooks render again. On the server nothing is notified.On the server it writes into the current request's context, and throws
[Twilight] No request context…outside one. Call it in handlers, effects, loaders or middleware, never while a component renders.
Gotchas
The engine overwrites what it owns: every navigation writes
location,routeIdandsettingsagain, and the root route writeslocale,settings,i18nandauthToken. A value you put in those fields lasts until the next navigation. Keep your own values inextras.extrasis replaced, not merged:updateTwilightContext({ extras: { banner } })removes acampaignstored before. Spread the currentextrasfirst, as the example does.A value written on the server stays there. Hydration copies settings, locale, i18n, auth token, location, page, route id and the app snippets and settings into the browser, nothing else (src/tanstack/router.tsx), so
extraswritten by a middleware isundefinedin the browser. Return what the browser needs from a loader.
Related
Reads the engine's context outside React: store settings, language, location, route id, auth token and the data cache.
runWithTwilightContextRuns a function inside a fresh request context on the server. twilightMiddleware() does this for every request, so themes rarely call it.
useRouteIdReturns the id of the page on screen, such as "cart" or "product.single", and renders the component again when the shopper navigates.
Source and docs
- Engine source:
packages/theme-engine/src/twilight/context.ts