diff --git a/src/AppContainer.dev.js b/src/AppContainer.dev.js
index 6741eda86..9b9888145 100644
--- a/src/AppContainer.dev.js
+++ b/src/AppContainer.dev.js
@@ -18,6 +18,8 @@ class AppContainer extends React.Component {
return null
}
+ static reactHotLoadable = false
+
state = {
error: null,
errorInfo: null,
diff --git a/src/global/generation.js b/src/global/generation.js
index 5d2795c4f..b4b38b064 100644
--- a/src/global/generation.js
+++ b/src/global/generation.js
@@ -1,7 +1,9 @@
+import { forEachKnownClass } from '../proxy/createClassProxy'
+
let generation = 1
let hotComparisonCounter = 0
let hotComparisonRuns = 0
-const nullFunction = () => {}
+const nullFunction = () => ({})
let onHotComparisonOpen = nullFunction
let onHotComparisonElement = nullFunction
let onHotComparisonClose = nullFunction
@@ -12,13 +14,20 @@ export const setComparisonHooks = (open, element, close) => {
onHotComparisonClose = close
}
-export const getElementComparisonHook = () => onHotComparisonElement
+export const getElementComparisonHook = component =>
+ onHotComparisonElement(component)
+export const getElementCloseHook = component => onHotComparisonClose(component)
export const hotComparisonOpen = () =>
hotComparisonCounter > 0 && hotComparisonRuns > 0
+const openGeneration = () => forEachKnownClass(onHotComparisonElement)
+
+export const closeGeneration = () => forEachKnownClass(onHotComparisonClose)
+
const incrementHot = () => {
if (!hotComparisonCounter) {
+ openGeneration()
onHotComparisonOpen()
}
hotComparisonCounter++
@@ -26,7 +35,7 @@ const incrementHot = () => {
const decrementHot = () => {
hotComparisonCounter--
if (!hotComparisonCounter) {
- onHotComparisonClose()
+ closeGeneration()
hotComparisonRuns++
}
}
diff --git a/src/proxy/constants.js b/src/proxy/constants.js
index dd6586276..cc667798e 100644
--- a/src/proxy/constants.js
+++ b/src/proxy/constants.js
@@ -5,3 +5,5 @@ export const REGENERATE_METHOD = `${PREFIX}regenerateByEval`
export const UNWRAP_PROXY = `${PREFIX}getCurrent`
export const CACHED_RESULT = `${PREFIX}cachedResult`
export const PROXY_IS_MOUNTED = `${PREFIX}isMounted`
+
+export const RENDERED_GENERATION = 'REACT_HOT_LOADER_RENDERED_GENERATION'
diff --git a/src/proxy/createClassProxy.js b/src/proxy/createClassProxy.js
index 14a681a71..a576a12d4 100644
--- a/src/proxy/createClassProxy.js
+++ b/src/proxy/createClassProxy.js
@@ -7,6 +7,7 @@ import {
CACHED_RESULT,
PROXY_IS_MOUNTED,
PREFIX,
+ RENDERED_GENERATION,
} from './constants'
import { identity, safeDefineProperty, proxyClassCreator } from './utils'
import { inject, checkLifeCycleMethods, mergeComponents } from './inject'
@@ -16,7 +17,11 @@ import {
isReactClass,
isReactClassInstance,
} from '../internal/reactUtils'
-import { getElementComparisonHook } from '../global/generation'
+import {
+ get as getGeneration,
+ getElementCloseHook,
+ getElementComparisonHook,
+} from '../global/generation'
const has = Object.prototype.hasOwnProperty
@@ -184,6 +189,7 @@ function createClassProxy(InitialComponent, proxyKey, options = {}) {
'componentDidMount',
target => {
target[PROXY_IS_MOUNTED] = true
+ target[RENDERED_GENERATION] = getGeneration()
instancesCount++
},
)
@@ -404,6 +410,7 @@ function createClassProxy(InitialComponent, proxyKey, options = {}) {
if (isFunctionalComponent || !ProxyComponent) {
// nothing
} else {
+ getElementCloseHook(ProxyComponent)
const classHotReplacement = () => {
checkLifeCycleMethods(ProxyComponent, NextComponent)
if (proxyGeneration > 1) {
@@ -418,7 +425,6 @@ function createClassProxy(InitialComponent, proxyKey, options = {}) {
Object.setPrototypeOf(ProxyComponent.prototype, NextComponent.prototype)
defineProxyMethods(ProxyComponent, NextComponent.prototype)
if (proxyGeneration > 1) {
- getElementComparisonHook()(ProxyComponent)
injectedMembers = mergeComponents(
ProxyComponent,
NextComponent,
@@ -427,6 +433,7 @@ function createClassProxy(InitialComponent, proxyKey, options = {}) {
injectedMembers,
)
}
+ getElementComparisonHook(ProxyComponent)
}
// Was constructed once
diff --git a/src/reactHotLoader.js b/src/reactHotLoader.js
index a6e083543..6be0d99bd 100644
--- a/src/reactHotLoader.js
+++ b/src/reactHotLoader.js
@@ -179,7 +179,7 @@ const reactHotLoader = {
React.Children.only.isPatchedByReactHotLoader = true
}
- reactHotLoader.reset()
+ // reactHotLoader.reset()
},
}
diff --git a/src/reconciler/componentComparator.js b/src/reconciler/componentComparator.js
index dece702f9..3107209b0 100644
--- a/src/reconciler/componentComparator.js
+++ b/src/reconciler/componentComparator.js
@@ -1,6 +1,7 @@
import {
getIdByType,
getProxyByType,
+ isColdType,
isRegisteredComponent,
updateProxyById,
} from './proxies'
@@ -97,7 +98,13 @@ export const hotComponentCompare = (oldType, newType, setNewType, baseType) => {
const hotActive = hotComparisonOpen()
let result = oldType === newType
- if (!isReloadableComponent(oldType) || !isReloadableComponent(newType)) {
+ if (
+ !isReloadableComponent(oldType) ||
+ !isReloadableComponent(newType) ||
+ isColdType(oldType) ||
+ isColdType(oldType) ||
+ 0
+ ) {
return result
}
diff --git a/src/reconciler/proxies.js b/src/reconciler/proxies.js
index af47cf0f1..72acd6b64 100644
--- a/src/reconciler/proxies.js
+++ b/src/reconciler/proxies.js
@@ -70,8 +70,10 @@ export const updateProxyById = (id, type, options = {}) => {
export const createProxyForType = (type, options) =>
getProxyByType(type) || updateProxyById(generateTypeId(), type, options)
+export const isColdType = type => blackListedProxies.has(type)
+
export const isTypeBlacklisted = type =>
- blackListedProxies.has(type) ||
+ isColdType(type) ||
(isCompositeComponent(type) &&
((configuration.ignoreSFC && !isReactClass(type)) ||
(configuration.ignoreComponents && isReactClass(type))))
diff --git a/src/reconciler/proxyAdapter.js b/src/reconciler/proxyAdapter.js
index 0293d4a4e..a304b2f03 100644
--- a/src/reconciler/proxyAdapter.js
+++ b/src/reconciler/proxyAdapter.js
@@ -10,10 +10,8 @@ import reconcileHotReplacement, {
unscheduleUpdate,
} from './index'
import configuration, { internalConfiguration } from '../configuration'
-import { forEachKnownClass } from '../proxy/createClassProxy'
import { EmptyErrorPlaceholder, logException } from '../errorReporter'
-
-export const RENDERED_GENERATION = 'REACT_HOT_LOADER_RENDERED_GENERATION'
+import { RENDERED_GENERATION } from '../proxy'
export const renderReconciler = (target, force) => {
// we are not inside parent reconcilation
@@ -89,6 +87,10 @@ function componentRender() {
{ error, errorInfo, component: this },
)
}
+
+ if (this.hotComponentUpdate) {
+ this.hotComponentUpdate()
+ }
try {
return this[OLD_RENDER].render.call(this)
} catch (renderError) {
@@ -111,7 +113,8 @@ function retryHotLoaderError() {
setComparisonHooks(
() => ({}),
- ({ prototype }) => {
+ component => {
+ const { prototype } = component
if (!prototype[OLD_RENDER]) {
const renderDescriptior = Object.getOwnPropertyDescriptor(
prototype,
@@ -128,31 +131,33 @@ setComparisonHooks(
}
delete prototype[ERROR_STATE]
},
- () =>
- forEachKnownClass(({ prototype }) => {
- if (prototype[OLD_RENDER]) {
- const { generation } = prototype[ERROR_STATE] || {}
-
- if (generation === getGeneration()) {
- // still in error.
- // keep render hooked
+ ({ prototype }) => {
+ if (prototype[OLD_RENDER]) {
+ const { generation } = prototype[ERROR_STATE] || {}
+
+ if (generation === getGeneration()) {
+ // still in error.
+ // keep render hooked
+ } else {
+ delete prototype.componentDidCatch
+ delete prototype.retryHotLoaderError
+ if (!prototype[OLD_RENDER].descriptor) {
+ delete prototype.render
} else {
- delete prototype.componentDidCatch
- delete prototype.retryHotLoaderError
- if (!prototype[OLD_RENDER].descriptor) {
- delete prototype.render
- } else {
- prototype.render = prototype[OLD_RENDER].descriptor
- }
- delete prototype[ERROR_STATE]
- delete prototype[OLD_RENDER]
+ prototype.render = prototype[OLD_RENDER].descriptor
}
+ delete prototype[ERROR_STATE]
+ delete prototype[OLD_RENDER]
}
- }),
+ }
+ },
)
setStandInOptions({
componentWillRender: asyncReconciledRender,
componentDidRender: proxyWrapper,
- componentDidUpdate: flushScheduledUpdates,
+ componentDidUpdate: component => {
+ component[RENDERED_GENERATION] = getGeneration()
+ flushScheduledUpdates()
+ },
})
diff --git a/test/AppContainer.dev.test.js b/test/AppContainer.dev.test.js
index fcbbd0e05..a583f3d2d 100644
--- a/test/AppContainer.dev.test.js
+++ b/test/AppContainer.dev.test.js
@@ -8,7 +8,10 @@ import { mapProps } from 'recompose'
import { polyfill } from 'react-lifecycles-compat'
import { AppContainer } from '../src/index.dev'
import RHL from '../src/reactHotLoader'
-import { increment as incrementGeneration } from '../src/global/generation'
+import {
+ closeGeneration,
+ increment as incrementGeneration,
+} from '../src/global/generation'
import { configureComponent } from '../src/utils.dev'
import configuration from '../src/configuration'
@@ -346,6 +349,8 @@ describe(`AppContainer (dev)`, () => {
const wrapper = mount(