-
Notifications
You must be signed in to change notification settings - Fork 4.3k
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
useBlockElement: return null until ref callback has time to clean up the old element #63565
Merged
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
On unmount, shouldn't it be set to
null
?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 was considering this, but I think it's not needed, it wouldn't have any effect. On unmount, the component is going away, and updating its local state is not needed, because nobody is going to read it.
But maybe we can add it for consistency sake. So that the behavior is indistinguishable from the classic "store ref as state" pattern:
In this case the
setEl
will be called withnull
on unmount.useBlockRefs
is basically the same pattern, store an element ref into state, but the ref and the state are in different components, and the store in the provider serves as a teleportation machine between them.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.
Wouldn't it be possible to for a block to disappear, while another component is using
useBlockElement
, which would then still point to an unmounted DOM node?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.
Before the block disappears, the ref callback is called and sets the ref to
null
. Then the observable map calls its listeners and inside theuseBlockElement
hook, thesetBlockElement
inside the listener is called, and sets the local state tonull
. Therefore, all the references to the unmounted DOM node are cleared.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 issue makes me thinking that our current API for reading the elements is not very good. Ideally it should work exactly like element refs. Like this:
The
blockElRef
would be set and unset in real time as the target element changes. The point is that it is identical to how refs to local elements work:Exactly the same thing, only in one case the element is local and in the other it's teleported from another location.
This is much better than the current
useBlockRef
hook that returns a ref with a syntheticref.current
getter.The
useBlockElementRef
primitive can be used to very easily implementuseBlockElement
that returns the element and triggers a rerender on change:This implementation also never has the bug with returning stale unmounted elements.
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.
Oh, sorry, I misread this as a change to the hook inside the block rather than a change to the hook in the consumer.
Yes, that alternative seems good to me. We should try it :)
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.
Implemented in #63799 🙂