Uh oh!
There was an error while loading. Please reload this page.
fix(Button): memoize call to merge.all - #2252
Conversation
🦋 Changeset detectedLatest commit: 9506801 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
size-limit report 📦
|
Definitely an improvement! Would be helpful to run the same or similar benchmarks from https://github.com/github/primer/issues/1191 (without any data) I wonder if we'll get a lot of benefit from cache hits in memo when if it includes user provided Alternative solution: How do you feel about inserting css for all variants on render and using then a data-attribute to set the style. This would remove the function calls for rendered to something like <buttonclassName="btn-h4sh" data-variant="primary" data-size="small"/>
// css:
.btn-h4sh {
// common and default styles
}
.btn-h4sh[data-variant=primary] {
// primary styles
} We use data-attributes for styling in some other places like ButtonCounter and ActionList divider |
joshblack
commented
Aug 23, 2022
Thanks so much @siddharthkp!
Great point, I moved it out of
Sounds great, in order to profile would you recommend pulling down their project / npm link'ing primer and running the same trace?
Happy to do it, would that be what you'd recommend? |
joshblack
commented
Aug 23, 2022
cc @pksjce if you have any recommendations for setting a baseline here and profiling different approaches! |
pksjce
commented
Aug 25, 2022
joshblack
commented
Aug 26, 2022
@pksjce definitely! I'll use that for some quick ad-hoc measurements locally to see what you all think 👀 ScenariosBaseline
useMemo (sxProp in dep array) CodeconstButtonBase=forwardRef<HTMLElement,ButtonProps>(({children,as: Component='button',sx: sxProp, ...props},forwardedRef): JSX.Element=>{const{leadingIcon: LeadingIcon,trailingIcon: TrailingIcon, variant ='default', size ='medium'}=propsconst{theme}=useTheme()consticonWrapStyles={display: 'inline-block'}constsxStyles=useMemo(()=>{returnmerge.all([getButtonStyles(theme),getSizeStyles(size,variant,false),getVariantStyles(variant,theme),(sxProp||{})asSxProp])},[theme,size,variant,sxProp])return(<StyledButtonas={Component}sx={sxStyles}{...props}ref={forwardedRef}>useMemo (merge at sx call site) CodeconstsxStyles=useMemo(()=>{returnmerge.all([getButtonStyles(theme),getSizeStyles(size,variant,false),getVariantStyles(variant,theme)])},[theme,size,variant])return(<StyledButtonas={Component}sx={merge(sxStyles,sxPropasSxProp)}{...props}ref={forwardedRef}>Summary
Include |
pksjce
commented
Aug 30, 2022
Thanks for that analysis! Yes, so as I understand we want to memoize the internal style calculations and merge the user styles at the call site.
Fixing these two issues would fundamentally improve perf of |







Reference: https://github.com/github/primer/issues/1191
This PR updates
ButtonBaseto memoize the call tomerge.allwithuseMemo. This seemed like the best next step when I was taking a look at the issue, let me know if I misunderstood the approach!A quick aside, I removed the default value of
sxso thatuseMemowouldn't be called each render. The fallback value has been moved to themerge.allcallMerge checklist