Creating a new React widget
Note: Check out the Adding a new feature doc to make sure you're trying to add the right type of feature to VA.gov.
Adding a new widget
All the static pages use the static-pages
entry bundle, so any JS code included from that file will be on all static pages. In order to add a widget, you'll want to create a function that loads your desired React components (or plain JS) asynchronously, and mounts to an element on the page with your widget id.
- Ensure your page includes the
static-pages
bundle:
title: My awesome widget page
layout: page.html
---
Note: The entryname
must be absent from the markdown file's front matter or the resulting HTML file will include ${entryname}.js
instead of static-pages.js
.
- Add a mount point element in the static content page your widget will live on:
<div data-widget-type="my-new-widget" id="someId"></div>
- Add a start up function to:
src/applications/static-pages/static-pages-entry.js
:
...
createMyWidget(store, widgetTypes.MY_NEW_WIDGET);
...
You should also add a constant for your widget type in src/applications/static-pages/widgetTypes.js
:
export default {
...
MY_NEW_WIDGET: 'my-new-widget',
...
}
- Write your create widget function:
export default async function createMyWidget(store, widgetType) {
const widget = document.querySelector(`[data-widget-type="${widgetType}"]`);
if (widget) {
// Load widget if there's a mount point for it
const {
default: MyNewWidget,
} = await import(/* webpackChunkName: "my-new-widget" */ '../../platform/site-wide/my-new-widget');
// Do whatever you need to do to start up your widget
ReactDOM.render(<MyNewWidget>, widget);
}
}
Note that we don't import the widget code unless there's a mount point in the DOM. This function will run on every page, so we want to make sure we only download the bulk of the widget code when we're actually going to use it.
Guidelines for using React on a static page
We should be careful to not create a bad user experience when using React on static pages. Here are some guidelines you should follow:
- JS and React take time to download, parse, and render. Make sure you are providing the appropriate feedback to users while that is happening, with a spinner or another method from the UX team.
- Make sure the page is still usable if your React code fails to work. This can mean it fails to download, an error occurs, or just handling the different login states a user can be in.
- Be aware of how much weight you're adding to the static-pages bundle and code-split/lazy load when it makes sense.
Running end-to-end tests on a widget
Before running end-to-end (e2e) tests for a widget, you must add an entry for your widget to src/applications/registry.scaffold.json
. This will allow a landing page to be generated for your widget so you can run end-to-end tests in vets-website
. An example entry looks something like:
{
"appName": "About VA Disability Ratings",
"rootUrl": "/disability/about-disability-ratings",
"widgetType": "disability-rating-calculator"
},
appName
: The name of the title that will be used for the page.rootUrl
: The relative url of the page that the widget will be mounted on.widgetType
: The name of thedata-widget-type
attribute that will be used to mount your widget on the page.