Post

Comprehensive Guide: Upgrading React from 16 to 17 2024-10-04

Comprehensive Guide: Upgrading React from 16 to 17

React 17 brought several changes that, while not introducing many new features, laid the groundwork for future improvements. This guide will walk you through the process of upgrading your React application from version 16 to 17, covering package updates, testing modifications, and common issues you might encounter.

1. Upgrade Helper

Before diving into the upgrade process, it’s worth mentioning the React Native Upgrade Helper:

React Native Upgrade Helper

This tool can provide valuable insights into the changes required for your specific project.

2. Updating Node Modules

The first step in the upgrade process is to update your package.json file with the new versions of React and related packages.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
-   "react": "^16.9.0",
+   "react": "^17.0.2",

-   "react-dom": "^16.9.0",
+   "react-dom": "^17.0.2",

-   "react-scripts": "^3.2.0",
+   "react-scripts": "^5.0.1",

-   "jest-fetch-mock": "^2.1.1",
+   "jest-fetch-mock": "^3.0.0",

+   "@babel/plugin-proposal-private-property-in-object": "^7.21.11",

-   "enzyme-adapter-react-16": "^1.14.0",
+   "@wojtekmaj/enzyme-adapter-react-17": "^0.4.1",

-   "enzyme": "^3.10.0",
+   "enzyme": "^3.11.0",

After updating these dependencies, run npm install or yarn install to install the new versions.

3. Fixing Tests

3.1 Use beforeEach instead of beforeAll

In your test files, replace beforeAll with beforeEach to ensure a fresh setup for each test:

1
2
3
    describe('index edge', () => {
-     beforeAll(() => {
+     beforeEach(() => {

3.2 Jest Changes (from 24 to 27)

Mocking with spyOn

The behavior of jest.spyOn has changed. You now need to explicitly mock the implementation:

1
2
3
4
-     jest.spyOn(_, 'shuffle') # call original but not with 27
+     jest.spyOn(_, 'shuffle').mockImplementation((items) => {
+       return items.reverse()
+     })

Handling _.once in multiple tests

To prevent issues with _.once across multiple tests, mock it in your test setup:

1
2
3
4
5
6
+import _ from 'underscore';
+
+jest.mock('underscore', () => ({
+  ...jest.requireActual('underscore'),
+  once: jest.fn(fn => fn) // Replace _.once with a passthrough function
+}));

3.3 Enabling Jest Fetch Mocks

Update your setupTests.js file:

1
2
3
4
5
6
# setupTests.js
-import fetchMock from 'jest-fetch-mock'
+import { enableFetchMocks } from 'jest-fetch-mock'

-global.fetch = fetchMock
+enableFetchMocks()

When mocking responses, use doMock():

1
2
3
4
5
     beforeEach((done) => {
-      fetch.mockResponseOnce(response)
+      fetch.doMock().mockResponseOnce(response)
       _request(dispatch).then(done)
     })

4. Fixing ESLint Warnings

4.1 Update .eslintrc

Add the following rules to your .eslintrc file:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
{
  "rules": {
    "import/no-anonymous-default-export": ["error", {
      "allowArray": false,
      "allowArrowFunction": false,
      "allowAnonymousClass": false,
      "allowAnonymousFunction": false,
      "allowCallExpression": false,
      "allowNew": false,
      "allowLiteral": false,
      "allowObject": true
    }]
  }
}

To automatically fix ESLint issues, you can use this command:

1
npx eslint --fix --ext .js,.jsx src|grep .js> files; vim `cat files|sort|tr '\n' ' '`

4.2 Refactor Default Exports

Replace anonymous default exports with named exports:

1
2
3
4
5
6
-export default {
+const actions = {
   get: getConfiguration,
 }
+
+export default actions

4.3 Remove Unused Imports

Clean up your imports by removing unused ones:

1
2
-import { CORRECT, INCORRECT } from '../../../../../constants'
+import { CORRECT } from '../../../../../constants'

Conclusion

Upgrading from React 16 to 17 involves several steps, from updating dependencies to modifying your test setup and addressing ESLint warnings. While the process may seem daunting, following this guide should help you navigate the upgrade smoothly. Remember to thoroughly test your application after the upgrade to ensure everything works as expected.

For more detailed information on the changes in React 17, refer to the official React 17 release notes.

This post is licensed under CC BY 4.0 by the author.