-
Notifications
You must be signed in to change notification settings - Fork 4.2k
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
SlotFill: remove explicit rerender from portal version #67471
Conversation
The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message.
To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook. |
@@ -20,18 +19,15 @@ import type { FillComponentProps } from '../types'; | |||
export default function Fill( { name, children }: FillComponentProps ) { | |||
const registry = useContext( SlotFillContext ); | |||
const slot = useObservableValue( registry.slots, name ); | |||
const [ , rerender ] = useReducer( () => [], [] ); | |||
const ref = useRef( { rerender } ); | |||
const instanceRef = useRef( {} ); |
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.
The rerender
API goes away and the fill now registers only an unique instance object. I'm renaming it from ref
to instance
when registering, something that @tyxla asked for in one of the previous PRs.
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.
Thanks!
}; | ||
const instance = instanceRef.current; | ||
registry.registerFill( name, instance ); | ||
return () => registry.unregisterFill( name, instance ); |
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 effect stays the same except renaming the ref
variable to instanceRef
etc.
ref: ref || slot?.ref, | ||
fillProps: fillProps || slot?.fillProps || {}, | ||
} ); | ||
slots.set( name, { ref, fillProps } ); |
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.
A drive-by change removing redundant code. All the registerSlot
calls always include both the ref
and fillProps
values. Inheriting them from the previous slot
value has no effect.
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.
Makes sense 👍
// Force update fills. | ||
slotFills.forEach( ( fill ) => fill.rerender() ); | ||
} | ||
slots.set( name, { ref, fillProps } ); |
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 is the key change in this PR! Instead of silently updating a field with slots.get( name ).fillProps = fillProps
, we call slots.set
. That sets a new value and triggers calling all observableMap
listeners, leading to automatic rerendering of all fills.
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.
Much clearer and more concise, looks great 🚀
}, [ registerSlot, unregisterSlot, name ] ); | ||
registry.registerSlot( name, ref, fillPropsRef.current ); | ||
return () => registry.unregisterSlot( name, ref ); | ||
}, [ registry, name ] ); |
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.
A mere style change: don't destructure fields of registry
. Simplifies the hook dependencies.
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.
LGTM, nice simplification and cleanup 🚀
@@ -20,18 +19,15 @@ import type { FillComponentProps } from '../types'; | |||
export default function Fill( { name, children }: FillComponentProps ) { | |||
const registry = useContext( SlotFillContext ); | |||
const slot = useObservableValue( registry.slots, name ); | |||
const [ , rerender ] = useReducer( () => [], [] ); | |||
const ref = useRef( { rerender } ); | |||
const instanceRef = useRef( {} ); |
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.
Thanks!
ref: ref || slot?.ref, | ||
fillProps: fillProps || slot?.fillProps || {}, | ||
} ); | ||
slots.set( name, { ref, fillProps } ); |
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.
Makes sense 👍
// Force update fills. | ||
slotFills.forEach( ( fill ) => fill.rerender() ); | ||
} | ||
slots.set( name, { ref, fillProps } ); |
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.
Much clearer and more concise, looks great 🚀
Flaky tests detected in efbd839. 🔍 Workflow run URL: https://github.com/WordPress/gutenberg/actions/runs/12121082461
|
Simplifies the
SlotFill
implementation (the portal "bubbles virtually" version by removing explicitrerender
API and its calls fromFill
. After this patch the rerender happens automatically when the slot in theslots
observableMap
is changed with theslots.set( name, ... )
call.How to test:
All unit tests and e2e tests should pass.