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 state leaking when a function component throws on server render #19212

Merged
merged 6 commits into from
Jul 8, 2020

Conversation

pmaccart
Copy link
Contributor

Summary

Reset the internal hooks state when preparing a component for hooks usage, rather than after a component finishes rendering. This fixes #19211, where the internal hooks state is not cleared if a function component throws an error while rendering.

Test Plan

@facebook-github-bot
Copy link

Hi @pmaccart!

Thank you for your pull request and welcome to our community. We require contributors to sign our Contributor License Agreement, and we don't seem to have you on file.

In order for us to review and merge your code, please sign at https://code.facebook.com/cla. If you are contributing on behalf of someone else (eg your employer), the individual CLA may not be sufficient and your employer may need to sign the corporate CLA.

If you have received this in error or have any questions, please contact us at cla@fb.com. Thanks!

@sizebot
Copy link

sizebot commented Jun 30, 2020

No significant bundle size changes to report.

Size changes (stable)

Generated by 🚫 dangerJS against 21fdac0

@sizebot
Copy link

sizebot commented Jun 30, 2020

No significant bundle size changes to report.

Size changes (experimental)

Generated by 🚫 dangerJS against 21fdac0

@gaearon
Copy link
Collaborator

gaearon commented Jun 30, 2020

Can you add a test that would have been failing before? That would make it easier to check the changes.

@gaearon
Copy link
Collaborator

gaearon commented Jun 30, 2020

Can we instead add resetHooksAfterThrow, mirroring what we do in ReactFiberHooks?

@FiberesimaJoseph

This comment has been minimized.

@codesandbox-ci
Copy link

codesandbox-ci bot commented Jul 7, 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 21fdac0:

Sandbox Source
React Configuration

@pmaccart pmaccart force-pushed the reset-hooks-state-before-render branch 6 times, most recently from 6dad98b to 46556a4 Compare July 7, 2020 16:11
@pmaccart pmaccart force-pushed the reset-hooks-state-before-render branch from 46556a4 to 398116c Compare July 7, 2020 16:23
@pmaccart
Copy link
Contributor Author

pmaccart commented Jul 7, 2020

@gaearon Thanks for the feedback, and sorry for the slow response.

I made a couple updates to the PR:

  1. Added a unit test that fails prior to the fix (64f35a1)
  2. Added a commit that implements a similar approach to what is taken in ReactFiberHooks -- eager to get your feedback on whether this approach is preferable, or whether we want to stick with resetting the state in the prepareToUseHooks function. Happy to go either way on this.

if (__DEV__) {
isInHookUserCodeInDev = false;
}

// These were reset above
// These were reset via the resetHooksState() call
Copy link
Collaborator

Choose a reason for hiding this comment

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

Let's just remove this comment?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

numberOfReRenders = 0;
renderPhaseUpdates = null;
workInProgressHook = null;
resetHooksState();
if (__DEV__) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Move this DEV-only block to reset too?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

@gaearon gaearon changed the title Reset internal hooks state before rendering Fix state leaking when a function component throws on server render Jul 8, 2020
@@ -202,24 +202,21 @@ export function finishHooks(

children = Component(props, refOrContext);
}
currentlyRenderingComponent = null;
Copy link
Collaborator

Choose a reason for hiding this comment

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

Did we lose currentlyRenderingComponent?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Oops, yes -- added that in as well.

@gaearon gaearon merged commit b85b476 into facebook:master Jul 8, 2020
@gaearon
Copy link
Collaborator

gaearon commented Jul 8, 2020

Looks good. Thx

trueadm pushed a commit to trueadm/react that referenced this pull request Jul 8, 2020
…acebook#19212)

* add unit test asserting internal hooks state is reset

* Reset internal hooks state before rendering

* reset hooks state on error

* Use expect...toThrow instead of try/catch in test

* reset dev-only hooks state inside resetHooksState

* reset currentlyRenderingComponent to null
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 hook state not cleared when rendering using ReactDOMServer if component errors
5 participants