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.
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
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.