-
-
Notifications
You must be signed in to change notification settings - Fork 380
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
Fixed lazy usage with Suspense and Error Boundary together #521
Changes from 8 commits
03eb6d9
d920619
c50669e
f85fcaa
790ad66
cc0f646
addb38f
6ab1221
3e30e69
11d34e8
dacc790
1ca1815
f9ef9c7
cf9763d
ac57625
df7a4d3
c888a5b
97158e2
4d41215
df79086
8d874f9
d0d4c39
a15d07a
72b28dd
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -151,16 +151,19 @@ function createLoadable({ resolve = identity, render, onLoad }) { | |
loadAsync() { | ||
if (!this.promise) { | ||
const { __chunkExtractor, forwardedRef, ...props } = this.props | ||
this.promise = ctor | ||
.requireAsync(props) | ||
|
||
const cachedPromise = this.getCache() | ||
|
||
this.promise = cachedPromise || ctor.requireAsync(props) | ||
|
||
if (options.suspense) this.setCache(this.promise) | ||
|
||
this.promise = this.promise | ||
.then(loadedModule => { | ||
const result = resolve(loadedModule, { Loadable }) | ||
if (options.suspense) { | ||
this.setCache(result) | ||
} | ||
this.safeSetState( | ||
{ | ||
result: resolve(loadedModule, { Loadable }), | ||
result, | ||
loading: false, | ||
}, | ||
() => this.triggerOnLoad(), | ||
|
@@ -184,15 +187,8 @@ function createLoadable({ resolve = identity, render, onLoad }) { | |
const { error, loading, result } = this.state | ||
|
||
if (options.suspense) { | ||
const cachedResult = this.getCache() | ||
if (!cachedResult) throw this.loadAsync() | ||
return render({ | ||
loading: false, | ||
fallback: null, | ||
result: cachedResult, | ||
options, | ||
props: { ...props, ref: forwardedRef }, | ||
}) | ||
const cachedPromise = this.getCache() | ||
if (!cachedPromise) throw this.loadAsync() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That would happen if you have two components? What if this component would be rendered twice? Probably the cache should hold information about the status of a cached item. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If you have 2 components at the same tree level, they should have different Keys (like in arrays), having different Keys makes them different instances with their own internal cache What are your thoughts on that? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You might code split absolutely everything, including a single There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I've added some tests for multiple rendered components |
||
} | ||
|
||
if (error) { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What if the cache is a bit obsolete?
What if it was rejected by any reason?
Now you are not able to restart the operation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would make the promise retryable if I wanted some async component to retry.. instead of re-rendering from the error boundary :) although there might be use cases for the re-render, I'll think for a bit about this
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Promise cannot be retryable once it resolved or rejected - those are final states.
And in case of some error the normal expectation nowadays is to throw that error, and handle it at the nearest boundary.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this was what I had in mind when I said making the "promise" retryable
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's good to have "retry" working out of the box, but usually, it's better to expose this ability to the user, as long as they might want to communicate the problem to the end-user.