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

feat: support React 17 #1557

Merged
merged 10 commits into from Sep 22, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 2 additions & 2 deletions examples/styled-components/package.json
Expand Up @@ -23,8 +23,8 @@
"dependencies": {
"babel-polyfill": "^6.26.0",
"emotion": "^8.0.12",
"react": "^16.13.1",
"react-dom": "^16.13.1",
"react": "^17.0.0-rc.2",
"react-dom": "^17.0.0-rc.2",
"react-emotion": "^9.2.12",
"react-hot-loader": "^4.12.21",
"react-spring": "^8.0.25",
Expand Down
36 changes: 13 additions & 23 deletions examples/styled-components/yarn.lock
Expand Up @@ -4118,14 +4118,6 @@ prop-types@^15.6.1:
loose-envify "^1.3.1"
object-assign "^4.1.1"

prop-types@^15.6.2:
version "15.6.2"
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.6.2.tgz#05d5ca77b4453e985d60fc7ff8c859094a497102"
integrity sha512-3pboPvLiWD7dkI3qf3KbUe6hKFKa52w+AE0VCqECtf+QHAKgOL37tTaNCnuX1nAAQ4ZhyP+kYVKf8rLmJ/feDQ==
dependencies:
loose-envify "^1.3.1"
object-assign "^4.1.1"

proxy-addr@~2.0.2:
version "2.0.2"
resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.2.tgz#6571504f47bb988ec8180253f85dd7e14952bdec"
Expand Down Expand Up @@ -4247,15 +4239,14 @@ rc@^1.2.7:
minimist "^1.2.0"
strip-json-comments "~2.0.1"

react-dom@^16.13.1:
version "16.13.1"
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.13.1.tgz#c1bd37331a0486c078ee54c4740720993b2e0e7f"
integrity sha512-81PIMmVLnCNLO/fFOQxdQkvEq/+Hfpv24XNJfpyZhTRfO0QcmQIF/PgCa1zCOj2w1hrn12MFLyaJ/G0+Mxtfag==
react-dom@^17.0.0-rc.2:
version "17.0.0-rc.2"
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-17.0.0-rc.2.tgz#7c13267e1e97d53d9a6395ef1acf1a44157dc38a"
integrity sha512-Nx6SK3s8dhQbKeOoRYPpQcYTrhojXw6nrX7Lb/rpMKyAp1wfhyzC3ukZtWczwILR9h4MzxtTLt/IIs8Bk4XqcQ==
dependencies:
loose-envify "^1.1.0"
object-assign "^4.1.1"
prop-types "^15.6.2"
scheduler "^0.19.1"
scheduler "0.20.0-rc.2"

react-emotion@^9.2.12:
version "9.2.12"
Expand Down Expand Up @@ -4307,14 +4298,13 @@ react-spring@^8.0.25:
"@babel/runtime" "^7.3.1"
prop-types "^15.5.8"

react@^16.13.1:
version "16.13.1"
resolved "https://registry.yarnpkg.com/react/-/react-16.13.1.tgz#2e818822f1a9743122c063d6410d85c1e3afe48e"
integrity sha512-YMZQQq32xHLX0bz5Mnibv1/LHb3Sqzngu7xstSM+vrkE5Kzr9xE0yMByK5kMoTK30YVJE61WfbxIFFvfeDKT1w==
react@^17.0.0-rc.2:
version "17.0.0-rc.2"
resolved "https://registry.yarnpkg.com/react/-/react-17.0.0-rc.2.tgz#3d454a888c119f5bde8ac016840aab8ecda22413"
integrity sha512-Z/qj0VWOF0e7VlUY2IhQr05vQ/gFSGlqmPMgxD4JytqmQxh5T7We0t5n1M98UmgJyRFTSbdCs58ZEyv6WwacWA==
dependencies:
loose-envify "^1.1.0"
object-assign "^4.1.1"
prop-types "^15.6.2"

"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:
version "2.3.6"
Expand Down Expand Up @@ -4556,10 +4546,10 @@ sax@^1.2.4:
resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9"
integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==

scheduler@^0.19.1:
version "0.19.1"
resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.19.1.tgz#4f3e2ed2c1a7d65681f4c854fa8c5a1ccb40f196"
integrity sha512-n/zwRWRYSUj0/3g/otKDRPMh6qv2SYMWNq85IEa8iZyAv8od9zDYpGSnpBEjNgcMNq6Scbu5KfIPxNF72R/2EA==
scheduler@0.20.0-rc.2:
version "0.20.0-rc.2"
resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.20.0-rc.2.tgz#5c48ac29e1a352a43c74cb5fc54c5ca94d8396fc"
integrity sha512-tgvUKHPbQr0fq5EfRd3S8hgohi/fI3h/gv1jxVb9IungCF/t2jUG946dlwgCxy8bnYvSIwRjcuw7eksDDpplLg==
dependencies:
loose-envify "^1.1.0"
object-assign "^4.1.1"
Expand Down
7 changes: 4 additions & 3 deletions package.json
Expand Up @@ -54,6 +54,7 @@
"devDependencies": {
"@hot-loader/react-dom": "^16.8.6",
"@types/react": "16",
"@wojtekmaj/enzyme-adapter-react-17": "^0.1.1",
"babel-cli": "^6.7.5",
"babel-core": "^6.26.3",
"babel-eslint": "^8.2.3",
Expand Down Expand Up @@ -99,9 +100,9 @@
"yarn-deduplicate": "^1.1.1"
},
"peerDependencies": {
"@types/react": "^15.0.0 || ^16.0.0",
"react": "^15.0.0 || ^16.0.0",
"react-dom": "^15.0.0 || ^16.0.0"
"@types/react": "^15.0.0 || ^16.0.0 || ^17.0.0 ",
"react": "^15.0.0 || ^16.0.0 || ^17.0.0 ",
"react-dom": "^15.0.0 || ^16.0.0 || ^17.0.0 "
},
"peerDependenciesMeta": {
"@types/react": {
Expand Down
46 changes: 2 additions & 44 deletions scripts/ci.sh
Expand Up @@ -8,47 +8,5 @@ echo "Linting"
yarn lint
echo "\n\n"

echo "Installing React 15"
yarn add react@15 react-dom@15 react-test-renderer@15 --pure-lockfile
echo "\n\n"

yarn test:react-dom:prepare

# echo "Running tests on React 15 - Babel ES2015"
# yarn test:es2015
# echo "\n\n"

# echo "Running tests on React 15 - Babel Modern"
# yarn test:modern
# echo "\n\n"
# echo "\n\n"

echo "Installing React 16.10"
yarn add react@16 react-dom@16.10 react-test-renderer@16.10 --pure-lockfile
echo "\n\n"

yarn test:react-dom:prepare

echo "Running tests on React 16.10 - Babel ES2015"
yarn test:es2015
echo "\n\n"

echo "Running tests on React 16.10 - Babel Modern"
yarn test:modern --coverage && codecov
echo "\n\n"



echo "Installing React 16:latest"
yarn add react@16 react-dom@16 react-test-renderer@16 --pure-lockfile
echo "\n\n"

yarn test:react-dom:prepare

echo "Running tests on React 16:latest - Babel ES2015"
yarn test:es2015
echo "\n\n"

echo "Running tests on React 16:latest - Babel Modern"
yarn test:modern --coverage && codecov
echo "\n\n"
./scripts/react-16.ci.sh
./scripts/react-17.ci.sh
14 changes: 14 additions & 0 deletions scripts/react-15.ci.sh
@@ -0,0 +1,14 @@
echo "Installing React 15"
yarn add react@15 react-dom@15 react-test-renderer@15 --pure-lockfile
echo "\n\n"

yarn test:react-dom:prepare

echo "Running tests on React 15 - Babel ES2015"
yarn test:es2015
echo "\n\n"

echo "Running tests on React 15 - Babel Modern"
yarn test:modern
echo "\n\n"
echo "\n\n"
29 changes: 29 additions & 0 deletions scripts/react-16.ci.sh
@@ -0,0 +1,29 @@
echo "Installing React 16.10"
yarn add react@16 react-dom@16.10 react-test-renderer@16.10 --pure-lockfile
echo "\n\n"

yarn test:react-dom:prepare

echo "Running tests on React 16.10 - Babel ES2015"
yarn test:es2015
echo "\n\n"

echo "Running tests on React 16.10 - Babel Modern"
yarn test:modern --coverage && codecov
echo "\n\n"



echo "Installing React 16:latest"
yarn add react@16 react-dom@16 react-test-renderer@16 --pure-lockfile
echo "\n\n"

yarn test:react-dom:prepare

echo "Running tests on React 16:latest - Babel ES2015"
yarn test:es2015
echo "\n\n"

echo "Running tests on React 16:latest - Babel Modern"
yarn test:modern --coverage && codecov
echo "\n\n"
13 changes: 13 additions & 0 deletions scripts/react-17.ci.sh
@@ -0,0 +1,13 @@
echo "Installing React 17"
yarn add react@17.0.0-rc.2 react-dom@17.0.0-rc.2 react-test-renderer@17.0.0-rc.2 --pure-lockfile
echo "\n\n"

yarn test:react-dom:prepare

echo "Running tests on React 17 - Babel ES2015"
yarn test:es2015
echo "\n\n"

echo "Running tests on React 17 - Babel Modern"
yarn test:modern --coverage && codecov
echo "\n\n"
3 changes: 3 additions & 0 deletions src/configuration.js
Expand Up @@ -58,6 +58,9 @@ const configuration = {
// Actively track lazy loaded components
trackTailUpdates: true,

// wrap lazy with AppProvider to allow independent updates
wrapLazy: true,

// react hot dom features enabled
IS_REACT_MERGE_ENABLED: false,
};
Expand Down
2 changes: 2 additions & 0 deletions src/hot.dev.js
Expand Up @@ -177,4 +177,6 @@ const hot = sourceModule => {
};
};

reactHotLoader.register(AppContainer, 'AppContainer', 'hot-dev');

export default hot;
68 changes: 54 additions & 14 deletions src/reconciler/fiberUpdater.js
@@ -1,3 +1,4 @@
/* eslint-disable no-underscore-dangle */
import React from 'react';
import configuration from '../configuration';
import { enterHotUpdate } from '../global/generation';
Expand All @@ -6,38 +7,77 @@ import { resolveType } from './resolver';

const lazyConstructor = '_ctor';

const getLazyConstructor = target => {
// React 16
if (target[lazyConstructor]) {
return target[lazyConstructor];
}

// React 17
if (target._payload) {
return target._payload._result;
}
return null;
};

const setLazyConstructor = (target, replacement) => {
replacement.isPatchedByReactHotLoader = true;

// React 16
if (target[lazyConstructor]) {
target[lazyConstructor] = replacement;
}
// React 17
else if (target._payload) {
target._payload._hotUpdated = true;
target._payload._result = replacement;
} else {
console.error('could not update lazy component');
}
};

const patched = fn => {
fn.isPatchedByReactHotLoader = true;
return fn;
};

const patchLazyConstructor = target => {
if (!configuration.trackTailUpdates && !target[lazyConstructor].isPatchedByReactHotLoader) {
const ctor = target[lazyConstructor];
target[lazyConstructor] = () =>
if (configuration.wrapLazy && !getLazyConstructor(target).isPatchedByReactHotLoader) {
const ctor = getLazyConstructor(target);
setLazyConstructor(target, () =>
ctor().then(m => {
const C = resolveType(m.default);
// chunks has been updated - new hot loader process is taking a place
enterHotUpdate();
if (!React.forwardRef) {
return {
default: props => (
default: patched(props => (
<AppContainer>
<C {...props} />
</AppContainer>
),
)),
};
}
return {
default: React.forwardRef((props, ref) => (
<AppContainer>
<C {...props} ref={ref} />
</AppContainer>
)),
default: patched(
// eslint-disable-next-line prefer-arrow-callback
React.forwardRef(function HotLoaderLazyWrapper(props, ref) {
return (
<AppContainer>
<C {...props} ref={ref} />
</AppContainer>
);
}),
),
};
});
target[lazyConstructor].isPatchedByReactHotLoader = true;
}),
);
}
};

export const updateLazy = (target, type) => {
const ctor = type[lazyConstructor];
if (target[lazyConstructor] !== type[lazyConstructor]) {
const ctor = getLazyConstructor(type);
if (getLazyConstructor(target) !== ctor) {
// just execute `import` and RHL.register will do the job
ctor();
}
Expand Down
14 changes: 14 additions & 0 deletions src/webpack/patch.js
Expand Up @@ -59,6 +59,20 @@ const additional = {
'if (current!== null&&hotCompareElements(current.type,element.type,hotUpdateChild(current)))',
],

'17.0.0-rc1': [
'function createFiberFromTypeAndProps(type, // React$ElementType\n' +
'key, pendingProps, owner, mode, lanes) {',
'function createFiberFromTypeAndProps(type, // React$ElementType\n' +
'key, pendingProps, owner, mode, lanes) {type = hotResolveType(type);',
],

'17.0.0-rc1-compact': [
'function createFiberFromTypeAndProps(type,// React$ElementType\n' +
'key,pendingProps,owner,mode,lanes){',
'function createFiberFromTypeAndProps(type,// React$ElementType\n' +
'key,pendingProps,owner,mode,lanes){type = hotResolveType(type);',
],

'16.8-type': [
'function createFiberFromTypeAndProps(type, // React$ElementType\nkey, pendingProps, owner, mode, expirationTime) {',
'function createFiberFromTypeAndProps(type, // React$ElementType\nkey, pendingProps, owner, mode, expirationTime) {type = hotResolveType(type);',
Expand Down
2 changes: 1 addition & 1 deletion test/hot/react-dom.integration.spec.js
Expand Up @@ -432,7 +432,7 @@ describe(`🔥-dom`, () => {

it('support lazy memo forward in Provider', () => {
setConfig({
trackTailUpdates: false,
wrapLazy: false,
});

const spy = jest.fn();
Expand Down
2 changes: 1 addition & 1 deletion test/hot/react-dom.no-integration.spec.js
Expand Up @@ -271,7 +271,7 @@ describe(`🔥-dom`, () => {

it('support lazy memo forward', () => {
setConfig({
trackTailUpdates: false,
wrapLazy: false,
});

const spy = jest.fn();
Expand Down
4 changes: 3 additions & 1 deletion testConfig/setupTests.js
Expand Up @@ -7,9 +7,11 @@ function getAdapter() {
return require('enzyme-adapter-react-15');
} else if (React.version.startsWith('16')) {
return require('enzyme-adapter-react-16');
} else if (React.version.startsWith('17')) {
return require('@wojtekmaj/enzyme-adapter-react-17');
}

return null;
throw new Error('this version of React is not supported by Enzyme');
}

const Adapter = getAdapter();
Expand Down