Skip to content

Conversation

@b4h0-c4t
Copy link

Summary

fixed #18768
This issue has two problems.

First problem

React.lazy did not perform an undefined check for moduleObject.

input

const Async = lazy(async () => {});

current

Uncaught undefined

fixed

Warning: lazy: Expected the result of a dynamic import() call. Instead received: undefined

Your code should look like: 
  const MyComponent = lazy(() => import('./MyComponent'))

Second problem

React.lazy didn't check if the result of executing the argument was thenable.
input

const Async = lazy(() => ({}));

current

Uncaught {}

fixed

lazy: Expects to receive an async function.

Test Plan

yarn test ReactLazy

@codesandbox-ci
Copy link

codesandbox-ci bot commented May 15, 2020

This pull request is automatically built and testable in CodeSandbox.

To see build info of the built libraries, click here or the icon next to each commit SHA.

Latest deployment of this branch, based on commit 3beb303:

Sandbox Source
jovial-sun-mggvz Configuration
frosty-dust-xjily Issue #18768

@sizebot
Copy link

sizebot commented May 15, 2020

No significant bundle size changes to report.

Size changes (experimental)

Generated by 🚫 dangerJS against 3beb303

@sizebot
Copy link

sizebot commented May 15, 2020

Comparing: 9d17b56...849c264

Critical size changes

Includes critical production bundles, as well as any change greater than 2%:

Name +/- Base Current +/- gzip Base gzip Current gzip
oss-stable/react-dom/cjs/react-dom.production.min.js = 127.29 kB 127.29 kB = 40.81 kB 40.81 kB
oss-experimental/react-dom/cjs/react-dom.production.min.js = 130.11 kB 130.11 kB = 41.75 kB 41.75 kB
facebook-www/ReactDOM-prod.classic.js = 404.72 kB 404.72 kB = 74.90 kB 74.90 kB
facebook-www/ReactDOM-prod.modern.js = 393.27 kB 393.27 kB = 73.09 kB 73.09 kB
facebook-www/ReactDOMForked-prod.classic.js = 404.72 kB 404.72 kB = 74.90 kB 74.90 kB

Significant size changes

Includes any change greater than 0.2%:

Expand to show
Name +/- Base Current +/- gzip Base gzip Current gzip
oss-experimental/react/cjs/react-unstable-shared-subset.production.min.js +1.00% 6.53 kB 6.59 kB +0.82% 2.68 kB 2.70 kB
oss-stable-semver/react/cjs/react.production.min.js +0.92% 7.04 kB 7.11 kB +0.78% 2.81 kB 2.84 kB
oss-stable/react/cjs/react.production.min.js +0.92% 7.04 kB 7.11 kB +0.78% 2.81 kB 2.84 kB
oss-experimental/react/cjs/react.production.min.js +0.86% 7.56 kB 7.63 kB +0.54% 2.94 kB 2.96 kB
facebook-react-native/react/cjs/React-prod.js +0.85% 16.66 kB 16.80 kB +1.12% 4.28 kB 4.33 kB
facebook-react-native/react/cjs/React-profiling.js +0.85% 16.66 kB 16.80 kB +1.12% 4.28 kB 4.33 kB
facebook-www/React-prod.modern.js +0.74% 16.82 kB 16.94 kB +0.71% 4.36 kB 4.39 kB
facebook-www/React-profiling.modern.js +0.74% 16.82 kB 16.94 kB +0.71% 4.36 kB 4.39 kB
facebook-www/React-prod.classic.js +0.73% 16.96 kB 17.09 kB +0.80% 4.40 kB 4.43 kB
facebook-www/React-profiling.classic.js +0.73% 16.96 kB 17.09 kB +0.80% 4.40 kB 4.43 kB
oss-stable-semver/react/umd/react.profiling.min.js +0.60% 10.93 kB 10.99 kB +0.36% 4.41 kB 4.43 kB
oss-stable/react/umd/react.profiling.min.js +0.60% 10.93 kB 10.99 kB +0.36% 4.41 kB 4.43 kB
oss-stable-semver/react/umd/react.production.min.js +0.60% 10.93 kB 10.99 kB +0.41% 4.41 kB 4.43 kB
oss-stable/react/umd/react.production.min.js +0.60% 10.93 kB 10.99 kB +0.41% 4.41 kB 4.43 kB
oss-experimental/react/umd/react.profiling.min.js +0.57% 11.39 kB 11.45 kB +0.29% 4.54 kB 4.56 kB
oss-experimental/react/umd/react.production.min.js +0.57% 11.39 kB 11.45 kB +0.31% 4.54 kB 4.56 kB
oss-experimental/react/cjs/react-unstable-shared-subset.development.js +0.27% 68.89 kB 69.08 kB +0.28% 18.66 kB 18.71 kB
oss-stable-semver/react/cjs/react.development.js +0.25% 74.50 kB 74.68 kB +0.22% 20.02 kB 20.06 kB
oss-stable/react/cjs/react.development.js +0.25% 74.50 kB 74.68 kB +0.22% 20.02 kB 20.06 kB
oss-experimental/react/cjs/react.development.js +0.25% 74.97 kB 75.15 kB +0.21% 20.05 kB 20.09 kB
oss-stable-semver/react/umd/react.development.js +0.20% 97.25 kB 97.45 kB +0.20% 25.02 kB 25.07 kB
oss-stable/react/umd/react.development.js +0.20% 97.25 kB 97.45 kB +0.20% 25.02 kB 25.07 kB
oss-experimental/react/umd/react.development.js +0.20% 97.74 kB 97.94 kB +0.16% 25.07 kB 25.11 kB

Generated by 🚫 dangerJS against 849c264

@b4h0-c4t b4h0-c4t force-pushed the fix-lazy-throw-error-object branch 2 times, most recently from 53110d8 to 92505e9 Compare May 15, 2020 09:30
@b4h0-c4t b4h0-c4t marked this pull request as draft May 15, 2020 09:55
@b4h0-c4t b4h0-c4t force-pushed the fix-lazy-throw-error-object branch from 92505e9 to 3beb303 Compare May 15, 2020 10:17
@b4h0-c4t b4h0-c4t marked this pull request as ready for review May 15, 2020 10:17
moduleObject => {
if (payload._status === Pending) {
const defaultExport = moduleObject.default;
const defaultExport = moduleObject && moduleObject.default;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similarly, why isn't this property access throwing a proper error that then is passed to the error handler?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should I use 'invariant' for the check?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If throwing error (invariant or other) in thenable.then, it error to be UnhandledPromiseRejectionWarning.
I think that it is a better solution than before the fix.

@b4h0-c4t b4h0-c4t requested a review from sebmarkbage May 27, 2020 09:07
@b4h0-c4t
Copy link
Author

@sebmarkbage
About the second conversation, I got some solutions.
I would like you to tell me which one is best.

1. Allowing the moduleObject to be undefined.
It is the current code.
I have interpreted the existing behavior in an expanded way.

2. Use invariant.

moduleObject => {
  if (payload._status === Pending) {
    invariant(
      moduleObject !== undefined,
      'lazy: lazy: Expected the result of a dynamic import() call. '
    );
    const defaultExport = moduleObject.default;
    // ... some pragram.

It can throw an error using invariant.
But, I think it is inappropriate because it causes UnhandledPromiseRejectionWarning.

3. Use Rejected

moduleObject => {
  if (payload._status === Pending) {
    // Transition to the next state.
    if(moduleObject !== undefined){
      const defaultExport = moduleObject.default;
      const resolved: ResolvedPayload<T> = (payload: any);
      resolved._status = Resolved;
      resolved._result = defaultExport;
    } else {
      const rejected: RejectedPayload = (payload: any);
      rejected._status = Rejected;
      rejected._result = error;
    }
    // ... some pragram.

It takes the "rejected status" to onFulFill.
it looks natural, but as far as I can see, the error is being managed by invariant.

@stale
Copy link

stale bot commented Aug 29, 2020

This pull request has been automatically marked as stale. If this pull request is still relevant, please leave any comment (for example, "bump"), and we'll keep it open. We are sorry that we haven't been able to prioritize reviewing it yet. Your contribution is very much appreciated.

@stale stale bot added the Resolution: Stale Automatically closed due to inactivity label Aug 29, 2020
@b4h0-c4t
Copy link
Author

bump

@stale stale bot removed the Resolution: Stale Automatically closed due to inactivity label Aug 30, 2020
@stale
Copy link

stale bot commented Dec 25, 2020

This pull request has been automatically marked as stale. If this pull request is still relevant, please leave any comment (for example, "bump"), and we'll keep it open. We are sorry that we haven't been able to prioritize reviewing it yet. Your contribution is very much appreciated.

@stale stale bot added the Resolution: Stale Automatically closed due to inactivity label Dec 25, 2020
@VitorLuizC
Copy link

bump

@stale stale bot removed the Resolution: Stale Automatically closed due to inactivity label Jan 19, 2021
@zoeyzou
Copy link

zoeyzou commented Jun 4, 2021

What is the status of this PR? throwing undefined is still happening

@b4h0-c4t
Copy link
Author

b4h0-c4t commented Jun 7, 2021

I think my turn to be over, but what do the maintainers think?

"366": "ReactDOM.createEventHandle: setListener called on an target that did not have a corresponding root. This is likely a bug in React.",
"367": "ReactDOM.createEventHandle: setListener called on an element target that is not managed by React. Ensure React rendered the DOM element.",
"368": "ReactDOM.createEventHandle: setListener called on an invalid target. Provide a valid EventTarget or an element managed by React.",
"368": "ReactDOM.createEventHandle: setListener called on an invalid target. Provide a vaid EventTarget or an element managed by React.",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not reviewing this PR, just glancing over it and noticed this change that looks to have been an accident and should be reverted.

@gaearon
Copy link
Collaborator

gaearon commented Jun 7, 2021

I think there is a misunderstanding here.

The original review asked: why is it throwing undefined instead of the original error propagating?

This question has not been answered as far as I can see. This is what you want to answer before making any code changes.

@gaearon
Copy link
Collaborator

gaearon commented Jun 7, 2021

I sent #21639 with potential fix. Not sure if it works yet.

@gaearon
Copy link
Collaborator

gaearon commented Jun 7, 2021

We ended up doing this differently (#21642), but thank you for nudging to get this done. I agree it was an annoying oversight.

@gaearon gaearon closed this Jun 7, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bug: React.lazy throws undefined instead of an Error object

8 participants