Routing and Navigation
Role
ReactWP uses React Router for browser history, but WordPress still owns the route payload.
That means navigation is split into two layers:
- React Router keeps the browser URL and history in sync
- ReactWP fetches, caches, and renders the actual route payload from WordPress
Main Files
src/themes/reactwp/js/inc/RouteService.jssrc/themes/reactwp/js/inc/useRouteTransition.jssrc/themes/reactwp/js/components/AppLink.jsxsrc/mu-plugins/plugins/reactwp/template/inc/routes/rest.php
Direct Load vs Client Navigation
On a direct page load:
- WordPress resolves the current object
RouteResolverturns it into a route payloadBootstrapinjects that route into the initial JSON payload- React mounts from that payload
On client-side navigation:
- React Router detects the requested location
- ReactWP asks the REST route endpoint for the normalized route payload
- the loader prepares the critical assets
- the page transition runs
- the new route is rendered without a full page reload
Route Fetching
The REST endpoint lives at:
reactwp/v1/route
The frontend usually reaches it through:
runtime.system.routeEndpoint
RouteService.js normalizes the returned payload so the runtime always gets a predictable route shape.
Route Cache
RouteService.js keeps an in-memory Map keyed by normalized pathname plus normalized search string.
That means:
- revisiting a page in the same session can reuse the existing payload
- a hover-prefetched route can be available faster on click
- back and forward navigation can also benefit from the same cached payload
Hashes are not part of route identity. ReactWP treats:
pathname + searchas the route keyhashas local scroll state
Important Cache Limitation
The route cache is session memory, not a live invalidation system.
If the content of a page changes in WordPress while the app is already open, a previously cached route can stay stale until:
- the page is fully reloaded
- the tab is reopened
- the cache is cleared by a future runtime change
ReactWP does not currently ship automatic route cache invalidation.
The ReactWP cache generation rotates Cache Storage and initial asset URLs, but an already-running tab still keeps its route memory until a full page load. Changing the server generation cannot mutate JavaScript memory in a remote open tab.
Prefetching
AppLink.jsx prefetches routes on:
- mouse enter
- focus
It does that by calling Loader.prepareRoute(...), which means the route payload and its critical asset preparation can already be in flight before the click happens.
Internal Navigation Outside #app
ReactWP also listens for clicks on internal anchors outside #app.
This matters for elements such as:
- portal-mounted header content
- other shell-level anchors rendered outside the main React tree
That behavior lives in useInternalNavigation.js.
If an anchor outside #app points to an internal URL, ReactWP can intercept it and turn it into a client-side navigation.
Forcing A Full Browser Navigation
If you want a shell-level anchor outside #app to bypass React navigation, set:
data-router="false"
on that raw anchor element.
This tells the internal navigation listener to leave the click alone so the browser can perform a normal page load.
History Arrows
Back and forward navigation use the same ReactWP route transition flow as normal internal links.
That is why the route transition layer and the route cache both matter for:
- normal clicks
- browser back
- browser forward
Query Strings and Hashes
ReactWP normalizes query strings through URLSearchParams. Repeated query keys become arrays in route.query.
A location such as /projects/?type=house#results is treated as:
- route identity:
/projects/?type=house - local scroll target:
#results
Hash-only links on the current route bypass the leave/enter transition. ReactWP refreshes the scroller and scrolls to the target after the browser frame is ready.
By default, a same-page AppLink or internal Button also writes the target hash to the URL and adds a browser history entry. Pass updateHash={false} when the click should scroll to the target without changing the visible URL. This option does not remove the link's href; it only changes how a normal click updates history. See Components for examples.
Recommended Components
Use these components when you want standard ReactWP navigation behavior:
AppLinkfor internal linksButtonwithtoor internalhreffor navigation actions
Use a raw anchor only when you intentionally want browser-native navigation behavior.