Open alexandec opened 2 years ago
Changes required:
react-router
to 5.1.2history
to 5.2.0history-v4
and change imports to history
<IndexRoute component={Introduction} key="/intro" />
to <Route exact path="/" component={Introduction} key="/intro" />
import { Link } from 'react-router'
to import { Link } from 'react-router-dom'
createHistory
to createBrowserHistory
Previously routes were defined using objects like this:
[
{
path: '/first',
component: FirstComponent
},
{
path: '/second',
component: SecondComponent
},
]
WIth the router upgrade, routes must instead be defined using router components, like this:
<Switch>
<Route path="/first">
<FirstComponent />
</Route>
<Route path="/second">
<SecondComponent />
</Route>
</Switch>
For an example of the correct route definition method in the upgraded react-router, see the vaos
app, which already uses the new method. vaos/routes.jsx
defines 4 top-level routes, each with an associated component. Here's a shortened version showing one route:
<VAOSApp>
<Switch>
<Route
path="/new-unenrolled-covid-19-vaccine-booking"
component={asyncLoader(() =>
import(/* webpackChunkName: "unenrolled-vaccine" */ './unenrolled-vaccine')
.then(({ UnenrolledVaccineSection, reducer }) => {
store.injectReducer('unenrolledVaccine', reducer);
return UnenrolledVaccineSection;
})
.catch(handleLoadError),
)}
...
/>
</Switch>
</VAOSApp>
Moving down into the UnenrolledVaccineSection
component, we can see child routes defined there:
<FormLayout>
<Switch>
<Route
path={`${match.url}/confirmation`}
component={ConfirmationPage}
/>
<Route path="/" component={PlanAheadPage} />
</Switch>
</FormLayout>
We'll have to adopt this approach in order to upgrade react-router. On the positive side, we can refactor route definitions first, prior to upgrading react-router. We don't have to refactor everything at once.
Currently we perform redirects like this:
indexRoute: { onEnter: (nextState, replace) => replace('/introduction') },
This is a commonly-used redirect for form rendering. These redirects need to be modified to use Redirect
instead, like:
<Route render={() => (<Redirect to="/introduction" />)} />
This change needs to be made in 29 locations.
Here is a POC to transform the existing route objects returned by createRoutesWithSaveInProgress()
into components suitable for use with the new react-router version. The file is src/applications/pre-need/routes.jsx
:
import React from 'react';
import { Switch, Route } from 'react-router-dom';
import { createRoutesWithSaveInProgress } from 'platform/forms/save-in-progress/helpers';
import formConfig from './config/form';
const routeObjects = createRoutesWithSaveInProgress(formConfig);
const routes = routeObjects.map((routeObject, i) => (
<Route
path={`/${routeObject.path}`}
component={props => (
<routeObject.component {...props} route={routeObject} />
)}
key={i}
/>
));
const route = <Switch>{routes}</Switch>;
export default route;
With this approach I was able to work my way through each route in the burials-and-memorials/pre-need/form-10007-apply-for-eligibility
form and reach the end (form submission). This shows that the approach works with our existing react-router version (3) so we can use it to prepare apps ahead of time, before upgrading.
However this solution isn't complete because we're putting all the child routes at the top level. The wrapper components are not used so the form layout isn't correct. I'll work on adding in those wrapper components next.
Apps marked as OLD-FORM use deprecated route definitions (JS objects) generated by the forms library. These apps cannot be updated to use the new react-router until the Design System team modifies the forms library route generation logic. This Design System support request covers the required updates.
Apps marked as OLD manually define their routes as JS objects. App owners can freely update these routes to use the new component approach.
Apps marked as NEW already define their routes using the new component approach. They do not require route definition changes.
Apps typically require further changes beyond route definitions, to address breaking changes in react-router. These are noted in the "Additional deprecations" column.
App | Route definitions | Additional deprecations |
---|---|---|
appeals/10182 | OLD-FORM | indexRoute, childRoutes, withRouter, old import |
ask-a-question | OLD-FORM | indexRoute, childRoutes |
auth | OLD | location.query |
beta-enrollment | OLD | childRoutes |
burials | OLD-FORM | indexRoute, childRoutes |
caregivers | OLD-FORM | indexRoute, childRoutes |
check-in/day-of | NEW | location.query, withRouter |
check-in/pre-check-in | NEW | location.query |
claims-status | NEW | IndexRedirect, IndexLink, nested child routes, withRouter, old import |
coronavirus-research/sign-up | OLD-FORM | indexRoute (customized), childRoutes |
coronavirus-research/update | OLD-FORM | indexRoute (customized), childRoutes |
coronavirus-screener | NEW | Old import |
coronavirus-vaccination-expansion | OLD-FORM | indexRoute, childRoutes, withRouter |
coronavirus-vaccination | NEW | indexRoute, nested child routes, location.query, withRouter, old import |
debt-letters | NEW | - |
disability-benefits/2346 | OLD-FORM | indexRoute, childRoutes |
disability-benefits/686c-674 | OLD-FORM | indexRoute, childRoutes |
disability-benefits/996 | OLD-FORM | indexRoute, childRoutes, old import |
disability-benefits/all-claims | OLD-FORM | indexRoute, childRoutes, old import |
disability-benefits/view-payments | NEW | Old import |
discharge-wizard | OLD | indexRoute, childRoutes, old import |
e-folders | OLD | - |
edu-benefits/0993 | OLD-FORM | indexRoute, childRoutes, withRouter |
edu-benefits/0994 | OLD-FORM | indexRoute, childRoutes |
edu-benefits/10203 | OLD-FORM | indexRoute, childRoutes |
edu-benefits/1990 | OLD-FORM | indexRoute, childRoutes |
edu-benefits/1990e | OLD-FORM | indexRoute, childRoutes |
edu-benefits/1990n | OLD-FORM | indexRoute, childRoutes |
edu-benefits/1990s | OLD-FORM | indexRoute, childRoutes |
edu-benefits/1995 | OLD-FORM | indexRoute, childRoutes |
edu-benefits/5490 | OLD-FORM | indexRoute, childRoutes |
edu-benefits/5495 | OLD-FORM | indexRoute, childRoutes |
edu-benefits/feedback-tool | OLD-FORM | indexRoute, childRoutes |
facility-locator | OLD | indexRoute, childRoutes, browserHistory, location.query, old import |
financial-status-report | OLD-FORM | indexRoute, childRoutes |
gi-sandbox | NEW | - |
gi | NEW | - |
hca | OLD-FORM | indexRoute, childRoutes |
health-care-questionnaire/list/questionnaire-list | NEW | - |
health-care-questionnaire/list | NEW | - |
health-care-questionnaire/questionnaire | OLD-FORM | indexRoute, childRoutes, withRouter |
letters | NEW | IndexRedirect, nested child routes, old import |
lgy/coe/form | OLD-FORM | indexRoute, childRoutes, old import |
lgy/coe/status | NEW | Old import |
login | OLD | indexRoute, childRoutes |
medical-copays | NEW | nested redirect |
messages | NEW | Old import |
mock-sip-form | OLD-FORM | indexRoute, childRoutes |
my-education-benefits | OLD-FORM | indexRoute, childRoutes |
pensions | OLD-FORM | indexRoute, childRoutes |
personalization/dashboard | - | Old import |
personalization/profile | NEW | Old import |
personalization/rated-disabilities | OLD | - |
personalization/search-representative | OLD-FORM | indexRoute, childRoutes |
personalization/view-dependents | OLD | - |
personalization/view-representative | NEW | Old import |
platform/user/authorization | - | location.query, browserHistory, withRouter |
platform/startup | - | browserHistory, old import |
post-911-gib-status | NEW | IndexRoute, nested child routes, old import |
pre-need | OLD-FORM | indexRoute, childRoutes |
sah/sahg | OLD-FORM | indexRoute, childRoutes |
search | OLD | location.query, withRouter |
terms-and-conditions | OLD | location.query |
vaos | NEW | - |
veteran-representative | OLD-FORM | indexRoute, childRoutes |
virtual-agent | NEW | Old import |
vre/28-1900 | OLD-FORM | indexRoute, childRoutes, old import |
vre/28-8832 | OLD-FORM | indexRoute, childRoutes |
You will need to change
import { Link } from 'react-router'
to
import { Link } from 'react-router-dom'
After doing so, you may notice unit test failures due to a missing context. The fix is to wrap the component under test in a router component, as described in the react-router testing guide.
The standard pattern for VSP apps is to call the startApp()
function to bootstrap the app. However, when you switch to the new react-router v5 route definitions and components, the existing startApp() function is no longer compatible. Instead use the new startApp() function in src/platform/startup/router.js. This should be a drop-in replacement.
In react-router v3 it was common to use the withRouter
HOC to access router information or perform navigation. In v5, withRouter is replaced by simple hooks like these:
import { useParams, useLocation, useHistory } from 'react-router-dom';
const params = useParams();
const location = useLocation();
const history = useHistory();
history.push(`${location.pathname}/more/${params.id}`);
The react-router documentation lists supported hooks with example usage.
Instead of placing your component inside the <Route render=...>
or <Route component=...>
props, just make your component a child of the Route component, like:
<Route path="/mypath">
<MyComponent />
</Route>
This method is cleaner because you will explicitly pass any props your component needs.
I don't remember by I closed this, but I reopened it based on today's Q3 planning conversation
The Forms Library Team is no longer working on a React Router V3 --> V5 upgrade. Given that V3 and V5 apps currently co-exist on Vets Website, and that any form apps on Router V3 will need a rewrite to migrate to the new VA Forms System Core (VAFSC) anyway, providing a migration path from React Router V3 to V5 is a step that doesn't provide a good return on time invested for the Forms Library Team.
For details on this decision, please see these Confluence pages:
The Forms Library Team will instead be working on a React Router V5 --> V6 upgrade, see this ticket for details.
Other tickets that reference React Router V3 -V5 upgrades:
@k80bowman @caw310 --- can we please chat about this soon. It is a blocker for us right now.
@laineymajor , let's chat on Monday. Katy is out sick this week.
@timwright12 can you specify what this is blocking within the ticket. Want to make sure we're tracking. Thanks!
Upgrade documentation and tips
For help upgrading routes and links in an app, see this documentation further down in the ticket.
Background
The official React router documentation recommends upgrading to v5.1 first, then moving to v6 as an additional step. This is the approach we're planning to take. In this ticket we'll only cover the upgrade from v3 (our current version) to v5.1.2.
See Upgrade react in vets-website to v17 for additional information and context.
Upgrading from react-router v3 to v5.1.2
react-router
to 5.1.2. Merge PRUpgrading from react-router v5.1.2 to v6.2.1 (future steps)
react-router
to 6.2.1. Merge PR