Skip to content

Commit c05396b

Browse files
authored
feat: support React 17 (#1557)
* feat: support React 17 * add react 17 tests * fix: use enzyme 16 adapter for React 17 * fix: add React 17 support for lazy, related to #1425 * ci uses absolute paths * fix: split trackTailUpdate into two options. Enable lazy wrapping by default * update tests * update yarn.lock * linting * reverse wrapLazy option effect
1 parent e44103a commit c05396b

15 files changed

+445
-98
lines changed

examples/styled-components/package.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@
2323
"dependencies": {
2424
"babel-polyfill": "^6.26.0",
2525
"emotion": "^8.0.12",
26-
"react": "^16.13.1",
27-
"react-dom": "^16.13.1",
26+
"react": "^17.0.0-rc.2",
27+
"react-dom": "^17.0.0-rc.2",
2828
"react-emotion": "^9.2.12",
2929
"react-hot-loader": "^4.12.21",
3030
"react-spring": "^8.0.25",

examples/styled-components/yarn.lock

+13-23
Original file line numberDiff line numberDiff line change
@@ -4118,14 +4118,6 @@ prop-types@^15.6.1:
41184118
loose-envify "^1.3.1"
41194119
object-assign "^4.1.1"
41204120

4121-
prop-types@^15.6.2:
4122-
version "15.6.2"
4123-
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.6.2.tgz#05d5ca77b4453e985d60fc7ff8c859094a497102"
4124-
integrity sha512-3pboPvLiWD7dkI3qf3KbUe6hKFKa52w+AE0VCqECtf+QHAKgOL37tTaNCnuX1nAAQ4ZhyP+kYVKf8rLmJ/feDQ==
4125-
dependencies:
4126-
loose-envify "^1.3.1"
4127-
object-assign "^4.1.1"
4128-
41294121
proxy-addr@~2.0.2:
41304122
version "2.0.2"
41314123
resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.2.tgz#6571504f47bb988ec8180253f85dd7e14952bdec"
@@ -4247,15 +4239,14 @@ rc@^1.2.7:
42474239
minimist "^1.2.0"
42484240
strip-json-comments "~2.0.1"
42494241

4250-
react-dom@^16.13.1:
4251-
version "16.13.1"
4252-
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.13.1.tgz#c1bd37331a0486c078ee54c4740720993b2e0e7f"
4253-
integrity sha512-81PIMmVLnCNLO/fFOQxdQkvEq/+Hfpv24XNJfpyZhTRfO0QcmQIF/PgCa1zCOj2w1hrn12MFLyaJ/G0+Mxtfag==
4242+
react-dom@^17.0.0-rc.2:
4243+
version "17.0.0-rc.2"
4244+
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-17.0.0-rc.2.tgz#7c13267e1e97d53d9a6395ef1acf1a44157dc38a"
4245+
integrity sha512-Nx6SK3s8dhQbKeOoRYPpQcYTrhojXw6nrX7Lb/rpMKyAp1wfhyzC3ukZtWczwILR9h4MzxtTLt/IIs8Bk4XqcQ==
42544246
dependencies:
42554247
loose-envify "^1.1.0"
42564248
object-assign "^4.1.1"
4257-
prop-types "^15.6.2"
4258-
scheduler "^0.19.1"
4249+
scheduler "0.20.0-rc.2"
42594250

42604251
react-emotion@^9.2.12:
42614252
version "9.2.12"
@@ -4307,14 +4298,13 @@ react-spring@^8.0.25:
43074298
"@babel/runtime" "^7.3.1"
43084299
prop-types "^15.5.8"
43094300

4310-
react@^16.13.1:
4311-
version "16.13.1"
4312-
resolved "https://registry.yarnpkg.com/react/-/react-16.13.1.tgz#2e818822f1a9743122c063d6410d85c1e3afe48e"
4313-
integrity sha512-YMZQQq32xHLX0bz5Mnibv1/LHb3Sqzngu7xstSM+vrkE5Kzr9xE0yMByK5kMoTK30YVJE61WfbxIFFvfeDKT1w==
4301+
react@^17.0.0-rc.2:
4302+
version "17.0.0-rc.2"
4303+
resolved "https://registry.yarnpkg.com/react/-/react-17.0.0-rc.2.tgz#3d454a888c119f5bde8ac016840aab8ecda22413"
4304+
integrity sha512-Z/qj0VWOF0e7VlUY2IhQr05vQ/gFSGlqmPMgxD4JytqmQxh5T7We0t5n1M98UmgJyRFTSbdCs58ZEyv6WwacWA==
43144305
dependencies:
43154306
loose-envify "^1.1.0"
43164307
object-assign "^4.1.1"
4317-
prop-types "^15.6.2"
43184308

43194309
"readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.4, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@~2.3.6:
43204310
version "2.3.6"
@@ -4556,10 +4546,10 @@ sax@^1.2.4:
45564546
resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9"
45574547
integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==
45584548

4559-
scheduler@^0.19.1:
4560-
version "0.19.1"
4561-
resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.19.1.tgz#4f3e2ed2c1a7d65681f4c854fa8c5a1ccb40f196"
4562-
integrity sha512-n/zwRWRYSUj0/3g/otKDRPMh6qv2SYMWNq85IEa8iZyAv8od9zDYpGSnpBEjNgcMNq6Scbu5KfIPxNF72R/2EA==
4549+
scheduler@0.20.0-rc.2:
4550+
version "0.20.0-rc.2"
4551+
resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.20.0-rc.2.tgz#5c48ac29e1a352a43c74cb5fc54c5ca94d8396fc"
4552+
integrity sha512-tgvUKHPbQr0fq5EfRd3S8hgohi/fI3h/gv1jxVb9IungCF/t2jUG946dlwgCxy8bnYvSIwRjcuw7eksDDpplLg==
45634553
dependencies:
45644554
loose-envify "^1.1.0"
45654555
object-assign "^4.1.1"

package.json

+4-3
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454
"devDependencies": {
5555
"@hot-loader/react-dom": "^16.8.6",
5656
"@types/react": "16",
57+
"@wojtekmaj/enzyme-adapter-react-17": "^0.1.1",
5758
"babel-cli": "^6.7.5",
5859
"babel-core": "^6.26.3",
5960
"babel-eslint": "^8.2.3",
@@ -99,9 +100,9 @@
99100
"yarn-deduplicate": "^1.1.1"
100101
},
101102
"peerDependencies": {
102-
"@types/react": "^15.0.0 || ^16.0.0",
103-
"react": "^15.0.0 || ^16.0.0",
104-
"react-dom": "^15.0.0 || ^16.0.0"
103+
"@types/react": "^15.0.0 || ^16.0.0 || ^17.0.0 ",
104+
"react": "^15.0.0 || ^16.0.0 || ^17.0.0 ",
105+
"react-dom": "^15.0.0 || ^16.0.0 || ^17.0.0 "
105106
},
106107
"peerDependenciesMeta": {
107108
"@types/react": {

scripts/ci.sh

+2-44
Original file line numberDiff line numberDiff line change
@@ -8,47 +8,5 @@ echo "Linting"
88
yarn lint
99
echo "\n\n"
1010

11-
echo "Installing React 15"
12-
yarn add react@15 react-dom@15 react-test-renderer@15 --pure-lockfile
13-
echo "\n\n"
14-
15-
yarn test:react-dom:prepare
16-
17-
# echo "Running tests on React 15 - Babel ES2015"
18-
# yarn test:es2015
19-
# echo "\n\n"
20-
21-
# echo "Running tests on React 15 - Babel Modern"
22-
# yarn test:modern
23-
# echo "\n\n"
24-
# echo "\n\n"
25-
26-
echo "Installing React 16.10"
27-
yarn add react@16 [email protected] [email protected] --pure-lockfile
28-
echo "\n\n"
29-
30-
yarn test:react-dom:prepare
31-
32-
echo "Running tests on React 16.10 - Babel ES2015"
33-
yarn test:es2015
34-
echo "\n\n"
35-
36-
echo "Running tests on React 16.10 - Babel Modern"
37-
yarn test:modern --coverage && codecov
38-
echo "\n\n"
39-
40-
41-
42-
echo "Installing React 16:latest"
43-
yarn add react@16 react-dom@16 react-test-renderer@16 --pure-lockfile
44-
echo "\n\n"
45-
46-
yarn test:react-dom:prepare
47-
48-
echo "Running tests on React 16:latest - Babel ES2015"
49-
yarn test:es2015
50-
echo "\n\n"
51-
52-
echo "Running tests on React 16:latest - Babel Modern"
53-
yarn test:modern --coverage && codecov
54-
echo "\n\n"
11+
./scripts/react-16.ci.sh
12+
./scripts/react-17.ci.sh

scripts/react-15.ci.sh

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
echo "Installing React 15"
2+
yarn add react@15 react-dom@15 react-test-renderer@15 --pure-lockfile
3+
echo "\n\n"
4+
5+
yarn test:react-dom:prepare
6+
7+
echo "Running tests on React 15 - Babel ES2015"
8+
yarn test:es2015
9+
echo "\n\n"
10+
11+
echo "Running tests on React 15 - Babel Modern"
12+
yarn test:modern
13+
echo "\n\n"
14+
echo "\n\n"

scripts/react-16.ci.sh

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
echo "Installing React 16.10"
2+
yarn add react@16 [email protected] [email protected] --pure-lockfile
3+
echo "\n\n"
4+
5+
yarn test:react-dom:prepare
6+
7+
echo "Running tests on React 16.10 - Babel ES2015"
8+
yarn test:es2015
9+
echo "\n\n"
10+
11+
echo "Running tests on React 16.10 - Babel Modern"
12+
yarn test:modern --coverage && codecov
13+
echo "\n\n"
14+
15+
16+
17+
echo "Installing React 16:latest"
18+
yarn add react@16 react-dom@16 react-test-renderer@16 --pure-lockfile
19+
echo "\n\n"
20+
21+
yarn test:react-dom:prepare
22+
23+
echo "Running tests on React 16:latest - Babel ES2015"
24+
yarn test:es2015
25+
echo "\n\n"
26+
27+
echo "Running tests on React 16:latest - Babel Modern"
28+
yarn test:modern --coverage && codecov
29+
echo "\n\n"

scripts/react-17.ci.sh

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
echo "Installing React 17"
2+
3+
echo "\n\n"
4+
5+
yarn test:react-dom:prepare
6+
7+
echo "Running tests on React 17 - Babel ES2015"
8+
yarn test:es2015
9+
echo "\n\n"
10+
11+
echo "Running tests on React 17 - Babel Modern"
12+
yarn test:modern --coverage && codecov
13+
echo "\n\n"

src/configuration.js

+3
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,9 @@ const configuration = {
5858
// Actively track lazy loaded components
5959
trackTailUpdates: true,
6060

61+
// wrap lazy with AppProvider to allow independent updates
62+
wrapLazy: true,
63+
6164
// react hot dom features enabled
6265
IS_REACT_MERGE_ENABLED: false,
6366
};

src/hot.dev.js

+2
Original file line numberDiff line numberDiff line change
@@ -177,4 +177,6 @@ const hot = sourceModule => {
177177
};
178178
};
179179

180+
reactHotLoader.register(AppContainer, 'AppContainer', 'hot-dev');
181+
180182
export default hot;

src/reconciler/fiberUpdater.js

+54-14
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
/* eslint-disable no-underscore-dangle */
12
import React from 'react';
23
import configuration from '../configuration';
34
import { enterHotUpdate } from '../global/generation';
@@ -6,38 +7,77 @@ import { resolveType } from './resolver';
67

78
const lazyConstructor = '_ctor';
89

10+
const getLazyConstructor = target => {
11+
// React 16
12+
if (target[lazyConstructor]) {
13+
return target[lazyConstructor];
14+
}
15+
16+
// React 17
17+
if (target._payload) {
18+
return target._payload._result;
19+
}
20+
return null;
21+
};
22+
23+
const setLazyConstructor = (target, replacement) => {
24+
replacement.isPatchedByReactHotLoader = true;
25+
26+
// React 16
27+
if (target[lazyConstructor]) {
28+
target[lazyConstructor] = replacement;
29+
}
30+
// React 17
31+
else if (target._payload) {
32+
target._payload._hotUpdated = true;
33+
target._payload._result = replacement;
34+
} else {
35+
console.error('could not update lazy component');
36+
}
37+
};
38+
39+
const patched = fn => {
40+
fn.isPatchedByReactHotLoader = true;
41+
return fn;
42+
};
43+
944
const patchLazyConstructor = target => {
10-
if (!configuration.trackTailUpdates && !target[lazyConstructor].isPatchedByReactHotLoader) {
11-
const ctor = target[lazyConstructor];
12-
target[lazyConstructor] = () =>
45+
if (configuration.wrapLazy && !getLazyConstructor(target).isPatchedByReactHotLoader) {
46+
const ctor = getLazyConstructor(target);
47+
setLazyConstructor(target, () =>
1348
ctor().then(m => {
1449
const C = resolveType(m.default);
1550
// chunks has been updated - new hot loader process is taking a place
1651
enterHotUpdate();
1752
if (!React.forwardRef) {
1853
return {
19-
default: props => (
54+
default: patched(props => (
2055
<AppContainer>
2156
<C {...props} />
2257
</AppContainer>
23-
),
58+
)),
2459
};
2560
}
2661
return {
27-
default: React.forwardRef((props, ref) => (
28-
<AppContainer>
29-
<C {...props} ref={ref} />
30-
</AppContainer>
31-
)),
62+
default: patched(
63+
// eslint-disable-next-line prefer-arrow-callback
64+
React.forwardRef(function HotLoaderLazyWrapper(props, ref) {
65+
return (
66+
<AppContainer>
67+
<C {...props} ref={ref} />
68+
</AppContainer>
69+
);
70+
}),
71+
),
3272
};
33-
});
34-
target[lazyConstructor].isPatchedByReactHotLoader = true;
73+
}),
74+
);
3575
}
3676
};
3777

3878
export const updateLazy = (target, type) => {
39-
const ctor = type[lazyConstructor];
40-
if (target[lazyConstructor] !== type[lazyConstructor]) {
79+
const ctor = getLazyConstructor(type);
80+
if (getLazyConstructor(target) !== ctor) {
4181
// just execute `import` and RHL.register will do the job
4282
ctor();
4383
}

src/webpack/patch.js

+14
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,20 @@ const additional = {
5959
'if (current!== null&&hotCompareElements(current.type,element.type,hotUpdateChild(current)))',
6060
],
6161

62+
'17.0.0-rc1': [
63+
'function createFiberFromTypeAndProps(type, // React$ElementType\n' +
64+
'key, pendingProps, owner, mode, lanes) {',
65+
'function createFiberFromTypeAndProps(type, // React$ElementType\n' +
66+
'key, pendingProps, owner, mode, lanes) {type = hotResolveType(type);',
67+
],
68+
69+
'17.0.0-rc1-compact': [
70+
'function createFiberFromTypeAndProps(type,// React$ElementType\n' +
71+
'key,pendingProps,owner,mode,lanes){',
72+
'function createFiberFromTypeAndProps(type,// React$ElementType\n' +
73+
'key,pendingProps,owner,mode,lanes){type = hotResolveType(type);',
74+
],
75+
6276
'16.8-type': [
6377
'function createFiberFromTypeAndProps(type, // React$ElementType\nkey, pendingProps, owner, mode, expirationTime) {',
6478
'function createFiberFromTypeAndProps(type, // React$ElementType\nkey, pendingProps, owner, mode, expirationTime) {type = hotResolveType(type);',

test/hot/react-dom.integration.spec.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -432,7 +432,7 @@ describe(`🔥-dom`, () => {
432432

433433
it('support lazy memo forward in Provider', () => {
434434
setConfig({
435-
trackTailUpdates: false,
435+
wrapLazy: false,
436436
});
437437

438438
const spy = jest.fn();

test/hot/react-dom.no-integration.spec.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -271,7 +271,7 @@ describe(`🔥-dom`, () => {
271271

272272
it('support lazy memo forward', () => {
273273
setConfig({
274-
trackTailUpdates: false,
274+
wrapLazy: false,
275275
});
276276

277277
const spy = jest.fn();

testConfig/setupTests.js

+3-1
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,11 @@ function getAdapter() {
77
return require('enzyme-adapter-react-15');
88
} else if (React.version.startsWith('16')) {
99
return require('enzyme-adapter-react-16');
10+
} else if (React.version.startsWith('17')) {
11+
return require('@wojtekmaj/enzyme-adapter-react-17');
1012
}
1113

12-
return null;
14+
throw new Error('this version of React is not supported by Enzyme');
1315
}
1416

1517
const Adapter = getAdapter();

0 commit comments

Comments
 (0)