When building a single-page app with Sitecore JSS and defining internal links in Sitecore content, you may notice that clicking the link in the JSS app does not act like a single page app. Instead the link click causes a full page refresh to occur, because the routing library used by the app is not aware that the link emitted by JSS can be treated as a route link.
Maybe you don’t want that to happen, because you like the fluidity of single-page apps or want to reduce bandwidth. Excellent! You’ve come to the right place.
The following examples use React, but the same architectural principles will translate well to Vue or Angular apps and the JSS field data schema is identical.
There are two places where we can receive links back from Sitecore:
Link Fields
Sitecore supports content fields that are explicitly hyperlinks (usually General Link fields, also referred to as CommonFieldTypes.GeneralLink
in JSS disconnected data). When returned these fields contain link data (a href
, optionally body text, CSS class, target, etc). In JSS apps, these are rendered using the Link
component like so:
1 | import { Link } from '@sitecore-jss/sitecore-jss-react'; |
This gives us normal anchor tag output in the DOM:
1 | <a href="/path">Link Text</a> |
But in react-router
, a link needs to be rendered using react-router-dom
‘s Link
component instead, for example:
1 | import { Link } from 'react-router-dom'; |
To make JSS general links render using react-router
links for internal links, we can create a component that conditionally chooses the link component like this:
1 | import React from 'react'; |
With this component, now your internal link values will be turned into router links and result in only a new fetch of route data instead of a page refresh!
Rich Text Fields
Rich Text fields are a more interesting proposition because they contain free text that is placed into the DOM, and we cannot inject RouterLink
components directly into the HTML blob. Instead we can use React’s DOM access to attach an event handler to the rich text markup after it’s rendered by React that will trigger route navigation.
Similar to the general link field handling, we can wrap the JSS default RichText
component with our own component that selects whether to bind the route handling events based on whether we’re editing the page or not:
1 | import React from 'react'; |
Now internal links entered in rich text fields will also be treated as route links.
Advanced Usages
These examples use simple internal link detection that consists of “starts with /
.” There are some edge cases that can defeat simple link detection, such as:
- Scheme-insensitive links (
//google.com
) that are HTTP or HTTPS depending on the current page. These are an antipattern; encrypt all your resources. - Links to static files (i.e. media files).
For use cases such as this, more advanced detection of internal links may be required that is situational for your implementation.