Prevent extraneous re-renders with next/dynamic (#11587)
* Prevent extraneous rerenders with loadables * Don't try to spread undefined * Allow ref to be memoized
This commit is contained in:
parent
5db180b221
commit
139da5ade2
1 changed files with 28 additions and 24 deletions
|
@ -164,9 +164,13 @@ function createLoadableComponent(loadFn, options) {
|
||||||
const context = React.useContext(LoadableContext)
|
const context = React.useContext(LoadableContext)
|
||||||
const state = useSubscription(subscription)
|
const state = useSubscription(subscription)
|
||||||
|
|
||||||
React.useImperativeHandle(ref, () => ({
|
React.useImperativeHandle(
|
||||||
|
ref,
|
||||||
|
() => ({
|
||||||
retry: subscription.retry,
|
retry: subscription.retry,
|
||||||
}))
|
}),
|
||||||
|
[]
|
||||||
|
)
|
||||||
|
|
||||||
if (context && Array.isArray(opts.modules)) {
|
if (context && Array.isArray(opts.modules)) {
|
||||||
opts.modules.forEach(moduleName => {
|
opts.modules.forEach(moduleName => {
|
||||||
|
@ -174,6 +178,7 @@ function createLoadableComponent(loadFn, options) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return React.useMemo(() => {
|
||||||
if (state.loading || state.error) {
|
if (state.loading || state.error) {
|
||||||
return React.createElement(opts.loading, {
|
return React.createElement(opts.loading, {
|
||||||
isLoading: state.loading,
|
isLoading: state.loading,
|
||||||
|
@ -187,6 +192,7 @@ function createLoadableComponent(loadFn, options) {
|
||||||
} else {
|
} else {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
}, [props, state])
|
||||||
}
|
}
|
||||||
|
|
||||||
LoadableComponent.preload = () => init()
|
LoadableComponent.preload = () => init()
|
||||||
|
@ -243,12 +249,12 @@ class LoadableSubscription {
|
||||||
|
|
||||||
this._res.promise
|
this._res.promise
|
||||||
.then(() => {
|
.then(() => {
|
||||||
this._update()
|
this._update({})
|
||||||
this._clearTimeouts()
|
this._clearTimeouts()
|
||||||
})
|
})
|
||||||
// eslint-disable-next-line handle-callback-err
|
// eslint-disable-next-line handle-callback-err
|
||||||
.catch(err => {
|
.catch(err => {
|
||||||
this._update()
|
this._update({})
|
||||||
this._clearTimeouts()
|
this._clearTimeouts()
|
||||||
})
|
})
|
||||||
this._update({})
|
this._update({})
|
||||||
|
@ -257,6 +263,9 @@ class LoadableSubscription {
|
||||||
_update(partial) {
|
_update(partial) {
|
||||||
this._state = {
|
this._state = {
|
||||||
...this._state,
|
...this._state,
|
||||||
|
error: this._res.error,
|
||||||
|
loaded: this._res.loaded,
|
||||||
|
loading: this._res.loading,
|
||||||
...partial,
|
...partial,
|
||||||
}
|
}
|
||||||
this._callbacks.forEach(callback => callback())
|
this._callbacks.forEach(callback => callback())
|
||||||
|
@ -268,12 +277,7 @@ class LoadableSubscription {
|
||||||
}
|
}
|
||||||
|
|
||||||
getCurrentValue() {
|
getCurrentValue() {
|
||||||
return {
|
return this._state
|
||||||
...this._state,
|
|
||||||
error: this._res.error,
|
|
||||||
loaded: this._res.loaded,
|
|
||||||
loading: this._res.loading,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
subscribe(callback) {
|
subscribe(callback) {
|
||||||
|
|
Loading…
Reference in a new issue