Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Upgrade react-router to v6 #3337

Merged
merged 38 commits into from
Feb 9, 2022
Merged

Upgrade react-router to v6 #3337

merged 38 commits into from
Feb 9, 2022

Conversation

nickclyde
Copy link
Member

@nickclyde nickclyde commented Feb 2, 2022

Related Issue or Background Info

Changes Proposed

  • Update react-router-dom to version 6.2.1. The major version upgrade from v5 to v6 introduced a number of breaking changes that touch a lot of different parts of the app. I followed this upgrade guide, making the following changes:
    • Switch to the hooks API introduced in v5.1 so that we don't have to pass the match prop down to child routes to access things like location and params. This is a huge improvement for code cleanliness!
    • <Route component={SomeComponent}> /> now becomes <Route element={<SomeComponent />} />, which allows us to easily pass props into routes! More info on the benefits of this here
    • Replace all uses of withRouter with hooks
    • Convert all <Redirect> components into <Navigate> components
    • Refactor the <GuardedRoute> and <ProtectedRoute> components into ones that get passed into an element prop of a <Route />, rather than returning a <Route /> component themselves. You can read a little more about why this change was made here.
    • Upgrade all <Switch> elements to <Routes> - see here, but the new <Routes> component allows relative routing!
    • Start using relative routes and links. You may have noticed before that some of our app components like PatientApp used to include an additional <Router> component with a basename prop so that we didn't have to prefix every route with /pxp. With v6 that's no longer needed because <Route> components can now be nested and the paths always include the parent route's path! The same goes for <Link> and <Navigate> components.
    • <Route> paths no longer need a leading slash, and can end in a wildcard * to match all subpaths. More info
    • Convert all uses of useHistory to useNavigate. More info
    • Related to the above, since useHistory is no longer available, we can't pass history into our Application Insights config. However, I don't think it was needed in the first place according to this comment. Since we have enableAutoRouteTracking: true set, it should already record any route changes automatically (see docs here)
    • Remove activeClassName and activeStyle props from Links
    • Last, the react-router team removed support for the <Prompt> component from this release in order to expedite the release. However, I was able to use a reimplementation found in this GH issue to keep that functionality since we use it in a couple places in the app. However, the team plans to readd it at some point, so I will keep an eye out and be sure to switch to the official API when it comes back.
  • These changes broke a lot of our tests, so I had to change a bunch of the tests, especially the ones that use <MemoryRouter>
  • Remove the react-router dependency. The react-router package includes everything from both react-router-dom and react-router-native, but we only use react-router-dom. Also updated all imports across the app to use react-router-dom
  • Added a REACT_APP_DISABLE_MAINTENANCE_BANNER environment variable that disables the maintenance banner, because it was causing issues on the e2e tests.
  • Added a /reload-app route which just redirects back to /. This allows us to retrigger the whoami query (for example after spoofing into an org) without actually refreshing the page and having to reload the bundle.

Additional Information

  • Another change that would be interesting is to use the <Outlet> component (docs here). This would allow us to place all of our <Route> components into a single tree in index.tsx, and then use the <Outlet> component in <Route> elements to refer to the child routes. This would be another big win for code cleanliness!
    • I took a stab at implementing, but wasn't sure how to pass state back up to the parent component, so I'm going to skip this for now.

Screenshots / Demos

Checklist for Author and Reviewer

Infrastructure

  • Consult the results of the terraform-plan job inside the "Terraform Checks" workflow run for this PR. Confirm that there are no unexpected changes!

Design

  • Any UI/UX changes have a designer as a reviewer, and changes have been approved
  • Any large-scale changes have been deployed to test, dev, or pentest and smoke-tested by both the engineering and design teams

Content

  • Any content changes (including new error messages) have been approved by content team

Support

  • Any changes that might generate new support requests have been flagged to the support team
  • Any changes to support infrastructure have been demo'd to support team

Testing

  • Includes a summary of what a code reviewer should verify

Changes are Backwards Compatible

  • Database changes are submitted as a separate PR
    • Any new tables that do not contain PII are accompanied by a GRANT SELECT to the no-PHI user
    • Any changes to tables that have custom no-PHI views are accompanied by changes to those views
      (including re-granting permission to the no-PHI user if need be)
    • Liquibase rollback has been tested locally using ./gradlew liquibaseRollbackSQL or liquibaseRollback
    • Each new changeset has a corresponding tag
  • GraphQL schema changes are backward compatible with older version of the front-end

Security

  • Changes with security implications have been approved by a security engineer (changes to authentication, encryption, handling of PII, etc.)
  • Any dependencies introduced have been vetted and discussed

Cloud

  • DevOps team has been notified if PR requires ops support
  • If there are changes that cannot be tested locally, this has been deployed to our Azure test, dev, or pentest environment for verification

@nickclyde nickclyde temporarily deployed to Dev February 2, 2022 22:48 Inactive
@nickclyde
Copy link
Member Author

Fixed the three bugs that were found when #3261 was merged to prod:

  1. Self-reg links are now prefixed with /app. However, the old links without /app prefixed will still be supported after Change app gateway to redirect self-registration links to /app #3344 is merged.
  2. Patients list pagination works again. Also added a unit test to ensure pagination doesn't break in the future.
  3. Edit facility form now loads the facility info in. Also fixed some tests here to prevent regression

Video:

router-bugs-fixed.mp4

@nickclyde nickclyde marked this pull request as ready for review February 4, 2022 20:39
@nickclyde
Copy link
Member Author

Also deploying to dev for more thorough smoke testing.

@nickclyde nickclyde temporarily deployed to Dev February 4, 2022 20:48 Inactive
@nickclyde
Copy link
Member Author

Copy link
Contributor

@emmastephenson emmastephenson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall the new changes look great! Smoke tested the following in dev and all worked well:

  • patient self-reg
  • patient results (texting works and opening link works)
  • pagination on results
  • pagination on people
  • user activation flow
  • signup flow
  • support admin flow

The one thing that looked off to me was the sub-nav for admins - it doesn't clear off "manage users" correctly when you nav over to "manage facilities"
Screen Shot 2022-02-04 at 2 11 18 PM

That's the only thing I can see that needs to be changed though!

@@ -62,6 +61,14 @@ describe("ManagePatients", () => {
expect(await screen.findByText(patients[1].lastName, { exact: false }));
expect(await screen.findByText(patients[2].lastName, { exact: false }));
});
it("can go to page 2", async () => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for adding a test here 👍

@@ -85,38 +92,248 @@ describe("ManagePatients", () => {

const patients = [
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(no-op) Holy cow, thanks for adding all these patients. Makes me want to up the priority of this ticket: #2929

emmastephenson
emmastephenson previously approved these changes Feb 4, 2022
Copy link
Contributor

@emmastephenson emmastephenson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@sonarqubecloud
Copy link

sonarqubecloud bot commented Feb 8, 2022

Kudos, SonarCloud Quality Gate passed!    Quality Gate passed

Bug A 0 Bugs
Vulnerability A 0 Vulnerabilities
Security Hotspot A 0 Security Hotspots
Code Smell A 3 Code Smells

82.1% 82.1% Coverage
0.0% 0.0% Duplication

@zdeveloper zdeveloper temporarily deployed to Test February 8, 2022 21:44 Inactive
Copy link
Contributor

@zdeveloper zdeveloper left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! deployed to test and smoke tested patient link and everything looks good to me! Have one minor question

newOrg?: boolean;
}

const FacilityFormContainer: any = (props: Props) => {
const { facilityId } = useParams();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any reason why is this being grabed from query params and not the props

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So in that case, the uuid after /facility is the id of the facility being edited in the form, whereas the facility query param refers to the currently selected facility in the nav bar. We want the id from the url params because that's the one we actually want to edit in the form.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That makes sense, I wish it was a bit clearer which facility is which, but that could be addressed in a future refactor.

Copy link
Contributor

@emmastephenson emmastephenson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@nickclyde nickclyde merged commit 15f9113 into main Feb 9, 2022
@nickclyde nickclyde deleted the nick/upgrade-react-router branch February 9, 2022 00:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants