-
Notifications
You must be signed in to change notification settings - Fork 2.7k
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(useAccessibility): make callbacks referentially stable #12185
Conversation
Asset size changesSize Auditor did not detect a change in bundle size for any component! Baseline commit: 49b255f5808c36413b36866c0ead9dcfa41d3252 (build) |
Perf AnalysisNo significant results to display. All results
Perf Analysis (Fluent)Perf comparison
Perf tests with no regressions
|
const definition = getAccessibility(debugName, behavior, mapPropsToBehavior(), rtl, actionHandlers); | ||
if (!slotHandlers.current[slotName]) { | ||
slotHandlers.current[slotName] = (e, ...args) => { | ||
const accessibilityHandler = definition.keyHandlers[slotName].onKeyDown; |
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.
keyHandlers
for a slot can be undefined. That was previously checked on line 38 but you don't have the check in the new code.
Also the previous contract was that the onKeyDown listener was added to an element only if it was handling anything. And that could change based on props
change. Now the listener is added and never removed.
I think it would be better to be unstable in these edge cases and add/remove the listener when needed.
You can use ButtonBehavior
to test both issues.
- It does not add the listener by default -> first issue.
- If you rerender with
as='div'
, it is supposed to add the listener, if you remove theas
later, it should remove the listener -> second issue.
Co-Authored-By: Roman Sudarikov <pompomon@users.noreply.github.com>
Co-Authored-By: Roman Sudarikov <pompomon@users.noreply.github.com>
@@ -11,7 +11,7 @@ export interface ReactAccessibilityBehavior extends AccessibilityDefinition { | |||
} | |||
|
|||
export type AccessibilityKeyHandlers = { | |||
[slotName: string]: AccessibilityHandlerProps; | |||
[slotName: string]: AccessibilityHandlerProps | undefined; |
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.
It can be undefined
, yep
@@ -2,6 +2,7 @@ import * as React from 'react'; | |||
|
|||
// useLayoutEffect() produces a warning with SSR rendering | |||
// https://medium.com/@alexandereardon/uselayouteffect-and-ssr-192986cdcf7a | |||
const useIsomorphicLayoutEffect = typeof window !== 'undefined' ? React.useLayoutEffect : React.useEffect; | |||
const useIsomorphicLayoutEffect = | |||
typeof window !== 'undefined' && process.env.NODE_ENV !== 'test' ? React.useLayoutEffect : React.useEffect; |
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.
Without process.env.NODE_ENV !== 'test'
it produces warning for tests because we use JSDom which has window
for sure
Pull request checklist
$ yarn change
Description of changes
This PR makes returned
onKeyDown
bygetA11yProps
fromuseAccessibility()
hook stable between rerenders, so it will stop to break memoized component (PureComponent
,React.memo()
) which can be used viaas
prop or astrigger
inPopup
&Tooltip
.Microsoft Reviewers: Open in CodeFlow