Skip to content
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

fix: invalid deferred data hanging response #6793

Merged
merged 7 commits into from
Jul 11, 2023
Merged

fix: invalid deferred data hanging response #6793

merged 7 commits into from
Jul 11, 2023

Conversation

jacob-ebey
Copy link
Member

Closes: #

  • Docs
  • Tests

Testing Strategy:

@changeset-bot
Copy link

changeset-bot bot commented Jul 7, 2023

🦋 Changeset detected

Latest commit: 4c2cfaa

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 18 packages
Name Type
@remix-run/react Patch
@remix-run/testing Patch
create-remix Patch
remix Patch
@remix-run/architect Patch
@remix-run/cloudflare Patch
@remix-run/cloudflare-pages Patch
@remix-run/cloudflare-workers Patch
@remix-run/css-bundle Patch
@remix-run/deno Patch
@remix-run/dev Patch
@remix-run/eslint-config Patch
@remix-run/express Patch
@remix-run/netlify Patch
@remix-run/node Patch
@remix-run/serve Patch
@remix-run/server-runtime Patch
@remix-run/vercel Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@benjaminsehl
Copy link
Member

Thank you sir!

Comment on lines 1003 to 1008
if (typeof data === "undefined") {
console.error(
`Deferred data for ${routeId} ${key} resolved to undefined, defaulting to null.`
);
data = null;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

I wonder if we could make this a TS error?

export function loader() {
  return defer({ 
    something: undefined,             // ❌
    lazy: Promise.resolve(undefined), // ❌

    else: null,                   // ✅
    lazy2: Promise.resolve(null), // ✅
  });
}

I didn't dig too deep but it looks like we have:

export type DeferFunction = <Data extends Record<string, unknown>>(
  data: Data, 
  init?: number | ResponseInit
) => TypedDeferredData<Data>;

I wonder if we could enhance that Record to allow something like NonNullable<unknown> | null | Promise<NonNullable<unknown> | null> as a value?

Copy link
Member Author

Choose a reason for hiding this comment

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

I'm honestly not sure how unknown would behave in this situation. @pcattori, what do you think?

Copy link
Contributor

Choose a reason for hiding this comment

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

IIRC I got the NonNullable<unknown> | null trick from Pedro for use in RR a while back: https://github.com/remix-run/react-router/blob/main/packages/router/utils.ts#L160

I believe NonNullable<unknown> allows anything except undefined/null and then you can add null back in

Copy link
Member Author

Choose a reason for hiding this comment

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

Let's do that in a followup PR if we want to.

Co-authored-by: Matt Brophy <matt@brophy.org>
@brophdawg11
Copy link
Contributor

Just clarifying - this should result in the warning and a resolution of null after the timeout? When I test this type of loader:

export function loader() {
  return defer({ data: Promise.resolve(undefined) });
}

It hangs for ~5 seconds then prints this in the console but does correctly resolve my <Await> with null:

Deferred data for routes/_index data resolved to undefined, defaulting to null.
Error: The render was aborted by the server without a reason.

I wasn't sure if this was supposed to still hit the timeout or it it should have flipped over and rendered null immediately?

However, if I introduce a delay I still get a Server timeout error boundary rendered - should that be defaulting over to null also?:

export function loader() {
  return defer({
    data: new Promise((r) => setTimeout(() => r(undefined), 1000)),
  });
}

@jacob-ebey
Copy link
Member Author

Just clarifying - this should result in the warning and a resolution of null after the timeout? When I test this type of loader:

export function loader() {
  return defer({ data: Promise.resolve(undefined) });
}

It hangs for ~5 seconds then prints this in the console but does correctly resolve my <Await> with null:

Deferred data for routes/_index data resolved to undefined, defaulting to null.
Error: The render was aborted by the server without a reason.

I wasn't sure if this was supposed to still hit the timeout or it it should have flipped over and rendered null immediately?

However, if I introduce a delay I still get a Server timeout error boundary rendered - should that be defaulting over to null also?:

export function loader() {
  return defer({
    data: new Promise((r) => setTimeout(() => r(undefined), 1000)),
  });
}

That should flip over immediately. I'll see if I can get a test in for that.

@brophdawg11
Copy link
Contributor

Alternate approach in remix-run/react-router#10690 - we'd still want to keep some of the improved error handling from here if we go with that.

@jacob-ebey
Copy link
Member Author

Dependent on remix-run/react-router#10690

@jacob-ebey jacob-ebey merged commit c8936ac into dev Jul 11, 2023
@jacob-ebey jacob-ebey deleted the deferred-hang branch July 11, 2023 23:06
@github-actions github-actions bot added the awaiting release This issue has been fixed and will be released soon label Jul 11, 2023
@github-actions
Copy link
Contributor

🤖 Hello there,

We just published version v0.0.0-nightly-c8936ac-20230712 which includes this pull request. If you'd like to take it for a test run please try it out and let us know what you think!

Thanks!

@github-actions
Copy link
Contributor

🤖 Hello there,

We just published version 1.19.0-pre.0 which includes this pull request. If you'd like to take it for a test run please try it out and let us know what you think!

Thanks!

@github-actions
Copy link
Contributor

🤖 Hello there,

We just published version 1.19.0 which includes this pull request. If you'd like to take it for a test run please try it out and let us know what you think!

Thanks!

@github-actions github-actions bot removed the awaiting release This issue has been fixed and will be released soon label Jul 19, 2023
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.

4 participants