Skip to content

Commit

Permalink
Merge pull request #1300 from gaearon/4.12.7
Browse files Browse the repository at this point in the history
4.12.7
  • Loading branch information
theKashey authored Jul 16, 2019
2 parents 0d665c8 + 4795456 commit 9b6c13c
Show file tree
Hide file tree
Showing 6 changed files with 70 additions and 32 deletions.
3 changes: 2 additions & 1 deletion .prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@ babel.js
index.js
patch.js
root.js
test/hot/react-dom
test/hot/react-dom
coverage
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,11 @@ There is only one condition for it - a non zero dependencies list.
🔥 useEffect(effect, ["hot"]); // the simplest way to make hook reloadable
```

**Plus**

* any hook would be reloaded on a function body change. Enabled by default, controlled by `reloadHooksOnBodyChange` option.
* you may configure RHL to reload any hook by setting `reloadLifeCycleHooks` option to true.

**To disable hooks reloading** - set configuration option:

```js
Expand Down
8 changes: 7 additions & 1 deletion src/configuration.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,15 @@ const configuration = {
// Allows SFC to be used, enables "intermediate" components used by Relay, should be disabled for Preact
allowSFC: true,

// Allow hot reload of effect hooks
// Allow reload of effect hooks with non zero dependency list
reloadHooks: true,

// Allow reload of mount effect hooks - zero deps
reloadLifeCycleHooks: false,

// Enables hook reload on hook body change
reloadHooksOnBodyChange: true,

// Disable "hot-replacement-render"
disableHotRenderer: false,

Expand Down
20 changes: 18 additions & 2 deletions src/reactHotLoader.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,24 @@ const forceSimpleSFC = { proxy: { pureSFC: true } };

const hookWrapper = hook => {
const wrappedHook = function(cb, deps) {
if (configuration.reloadHooks) {
return hook(cb, deps && deps.length > 0 ? [...deps, getHotGeneration()] : deps);
if (configuration.reloadHooks && deps) {
const inputs = [...deps];

// reload hooks which have changed string representation
if (configuration.reloadHooksOnBodyChange) {
inputs.push(String(cb));
}

if (
// reload hooks with dependencies
deps.length > 0 ||
// reload all hooks of option is set
(configuration.reloadLifeCycleHooks && deps.length === 0)
) {
inputs.push(getHotGeneration());
}

return hook(cb, inputs);
}
return hook(cb, deps);
};
Expand Down
50 changes: 27 additions & 23 deletions src/reconciler/componentComparator.js
Original file line number Diff line number Diff line change
Expand Up @@ -182,41 +182,45 @@ const compareComponents = (oldType, newType, setNewType, baseType) => {
const knownPairs = new WeakMap();
const emptyMap = new WeakMap();

const getKnownPair = (oldType, newType) => {
const pair = knownPairs.get(oldType) || emptyMap;
return pair.get(newType);
};

export const hotComponentCompare = (oldType, preNewType, setNewType, baseType) => {
const hotActive = hotComparisonOpen();
const newType = configuration.integratedResolver ? resolveType(preNewType) : preNewType;
let result = oldType === newType;

if (!hotActive) {
return result;
}
// TODO: find out the root cause
// we could not use "fast result" here - go a full part to update a fiber.
// const knownType = getKnownPair(oldType, newType);
// if (knownType !== undefined) {
// return knownType;
// }

if (
!isReloadableComponent(oldType) ||
!isReloadableComponent(newType) ||
isColdType(oldType) ||
isColdType(oldType) ||
!oldType ||
!newType ||
0
) {
return result;
}
let result = oldType === newType;

// comparison should be active only if hot update window
// or it would merge components it shall not
if (hotActive) {
// pre fail components which could not be merged
if (
!isReloadableComponent(oldType) ||
!isReloadableComponent(newType) ||
isColdType(oldType) ||
isColdType(oldType) ||
!oldType ||
!newType ||
0
) {
return result;
}

result = compareComponents(oldType, newType, setNewType, baseType);
const pair = knownPairs.get(oldType) || new WeakMap();
pair.set(newType, result);
knownPairs.set(oldType, pair);
return result;
}

if (result) {
return result;
}

const pair = knownPairs.get(oldType) || emptyMap;
return pair.get(newType) || false;
// result - true if components are equal, or were "equal" at any point in the past
return result || getKnownPair(oldType, newType) || false;
};
16 changes: 11 additions & 5 deletions src/reconciler/resolver.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,23 @@ import configuration, { internalConfiguration } from '../configuration';
const shouldNotPatchComponent = type => isTypeBlacklisted(type);

export function resolveType(type, options = {}) {
const element = { type };
if (isLazyType(element) || isMemoType(element) || isForwardType(element) || isContextType(element)) {
return getProxyByType(type) || type;
}

// fast return
if (!isCompositeComponent(type) || isProxyType(type)) {
return type;
}

const element = { type };

// fast meta
if (typeof element === 'object') {
if (isLazyType(element) || isMemoType(element) || isForwardType(element) || isContextType(element)) {
return getProxyByType(type) || type;
}
}

const existingProxy = getProxyByType(type);

// cold API
if (shouldNotPatchComponent(type)) {
return existingProxy ? existingProxy.getCurrent() : type;
}
Expand Down

0 comments on commit 9b6c13c

Please sign in to comment.