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

More accurate 'why did this render' wording #17068

Closed

Conversation

pelotom
Copy link

@pelotom pelotom commented Oct 11, 2019

After using the new devtools profiler (which is awesome btw!) I discovered that one of my components was rerendering because "the parent component rendered", despite being React.memoed and taking no props, which seemed like an impossibility (see twitter thread documenting my confusion). I eventually discovered that it was in fact updating due to context changes, and @bvaughn helpfully pointed out that the message was a fallback used when the component rerendered due to reasons other than state and props changing.

This PR attempts to make the wording a little more accurate: in addition to adding the "or context changed" caveat, it seems like "Internal state changed" is a more accurate description than "Hooks changed", because updates due to the useContext hook don't fall in that category. Ideally in the special case where the component is memoized the message could definitively say the update was due to a context change, but I'm not sure how to detect that situation 🙂

@sizebot
Copy link

sizebot commented Oct 11, 2019

No significant bundle size changes to report.

Generated by 🚫 dangerJS against dc94f8e

Copy link
Contributor

@bvaughn bvaughn left a comment

Choose a reason for hiding this comment

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

Thanks for the initiative. Left some thoughts.

@@ -167,7 +167,7 @@ function WhatChanged({
if (changeDescription.didHooksChange) {
changes.push(
<div key="hooks" className={styles.WhatChangedItem}>
Hooks changed
Internal state changed
Copy link
Contributor

Choose a reason for hiding this comment

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

Slight preference for "hooks" since people know what that means at least. "Internal state" sounds like it might refer to React internals or something else.

Copy link
Author

Choose a reason for hiding this comment

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

What about just "State changed"? What I found confusing was that changes due to useContext won't show up as "Hooks changed".

Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah, that's understandable. Most hooks aren't stateful in a way that triggers re-renders.

I'm not sure if "state changed" is better than "hooks changed" to be honest.

@@ -207,7 +207,7 @@ function WhatChanged({
if (changes.length === 0) {
changes.push(
<div key="nothing" className={styles.WhatChangedItem}>
The parent component rendered.
The parent component rendered or context changed
Copy link
Contributor

Choose a reason for hiding this comment

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

FWIW, we can detect a context change for class components, so we probably only want to show this additional warning if we're inspecting a function component.

Copy link
Author

@pelotom pelotom Oct 11, 2019

Choose a reason for hiding this comment

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

Sure, how do I detect that situation?

BTW, can't we also detect a context change for function components, simply by the process of elimination? If it's not due to state or prop changes and it's memoized, then it must be due to context changes, right?

Copy link
Contributor

Choose a reason for hiding this comment

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

Sure, how do I detect that situation?

You can use the type attribute to differentiate between a class component (ElementTypeClass) and a function component (ElementTypeFunction, ElementTypeMemo, or ElementTypeForwardRef).

BTW, can't we also detect a context change for function components, simply by the process of elimination? If it's not due to state or prop changes and it's memoized, then it must be due to context changes, right?

I think that may be a shaky assumption.

Currently the only two hooks that directly trigger a re-render are useReducer and useState (which is built on top of useReducer). The rest of them are either reactive or at least indirect (like useContext). I'm not sure if this will always be the case though.

So I guess we could show a more meaningful message if memoized props and state were shallowly equal and element type was ElementTypeMemo but this feels fragile and wouldn't cover some more ambiguous cases. If we show a more specific message in some cases, but not in others- that alone could cause confusion. ("It's not a context change, because if it would DevTools would say so like it did before.")

@stale
Copy link

stale bot commented Jan 9, 2020

This pull request has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contribution.

@stale stale bot added the Resolution: Stale Automatically closed due to inactivity label Jan 9, 2020
@stale
Copy link

stale bot commented Jan 16, 2020

Closing this pull request after a prolonged period of inactivity. If this issue is still present in the latest release, please ask for this pull request to be reopened. Thank you!

@stale stale bot closed this Jan 16, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
CLA Signed Resolution: Stale Automatically closed due to inactivity
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants