Skip to content

Commit 45f2d91

Browse files
authored
fix: use stable promises for load/preload/React (#858)
1 parent 33cb54d commit 45f2d91

File tree

2 files changed

+35
-31
lines changed

2 files changed

+35
-31
lines changed

packages/component/src/createLoadable.js

+34-30
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,37 @@ function createLoadable({
8989
return Component
9090
}
9191

92+
const cachedLoad = props => {
93+
const cacheKey = getCacheKey(props)
94+
let promise = cache[cacheKey]
95+
96+
if (!promise || promise.status === STATUS_REJECTED) {
97+
promise = ctor.requireAsync(props)
98+
promise.status = STATUS_PENDING
99+
100+
cache[cacheKey] = promise
101+
102+
promise.then(
103+
() => {
104+
promise.status = STATUS_RESOLVED
105+
},
106+
error => {
107+
console.error(
108+
'loadable-components: failed to asynchronously load component',
109+
{
110+
fileName: ctor.resolve(props),
111+
chunkName: ctor.chunkName(props),
112+
error: error ? error.message : error,
113+
},
114+
)
115+
promise.status = STATUS_REJECTED
116+
},
117+
)
118+
}
119+
120+
return promise
121+
}
122+
92123
class InnerLoadable extends React.Component {
93124
static getDerivedStateFromProps(props, state) {
94125
const cacheKey = getCacheKey(props)
@@ -270,33 +301,7 @@ function createLoadable({
270301
resolveAsync() {
271302
const { __chunkExtractor, forwardedRef, ...props } = this.props
272303

273-
let promise = this.getCache()
274-
275-
if (!promise) {
276-
promise = ctor.requireAsync(props)
277-
promise.status = STATUS_PENDING
278-
279-
this.setCache(promise)
280-
281-
promise.then(
282-
() => {
283-
promise.status = STATUS_RESOLVED
284-
},
285-
error => {
286-
console.error(
287-
'loadable-components: failed to asynchronously load component',
288-
{
289-
fileName: ctor.resolve(this.props),
290-
chunkName: ctor.chunkName(this.props),
291-
error: error ? error.message : error,
292-
},
293-
)
294-
promise.status = STATUS_REJECTED
295-
},
296-
)
297-
}
298-
299-
return promise
304+
return cachedLoad(props)
300305
}
301306

302307
render() {
@@ -343,12 +348,11 @@ function createLoadable({
343348

344349
// In future, preload could use `<link rel="preload">`
345350
Loadable.preload = props => {
346-
cache[getCacheKey()] = ctor.requireAsync(props);
351+
Loadable.load(props)
347352
}
348353

349354
Loadable.load = props => {
350-
cache[getCacheKey()] = ctor.requireAsync(props);
351-
return cache[getCacheKey()];
355+
return cachedLoad(props)
352356
}
353357

354358
return Loadable

packages/component/src/loadable.test.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ describe('#loadable', () => {
115115
const { container } = render(<Component />)
116116
expect(container).toBeEmpty()
117117
await wait(() => expect(container).toHaveTextContent('loaded'))
118-
expect(load).toHaveBeenCalledTimes(2)
118+
expect(load).toHaveBeenCalledTimes(1)
119119
})
120120

121121
it('supports commonjs default export', async () => {

0 commit comments

Comments
 (0)