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

Performance tuning #1274

Merged
merged 10 commits into from
Jul 22, 2021
Merged

Performance tuning #1274

merged 10 commits into from
Jul 22, 2021

Conversation

mshwery
Copy link
Contributor

@mshwery mshwery commented Jul 19, 2021

Overview
This PR addresses a bunch of small performance gains, especially for components that are used in large numbers (like inside Tables).

There are no breaking or obvious functional changes, but it does fix a few bugs in the stories – like editable cells appearing in the left hand corner of the screen 😬

Screenshots (if applicable)
NA

Documentation

  • Updated Typescript types and/or component PropTypes
  • Added / modified component docs
  • Added / modified Storybook stories

@netlify
Copy link

netlify bot commented Jul 19, 2021

✔️ Deploy Preview for evergreen-storybook ready!

🔨 Explore the source changes: 0721365

🔍 Inspect the deploy log: https://app.netlify.com/sites/evergreen-storybook/deploys/60f8e804d8c2b400084d6145

😎 Browse the preview: https://deploy-preview-1274--evergreen-storybook.netlify.app

<Popover
bringFocusInside={false}
isShown={isShown}
minWidth={popoverMinWidth}
position={position || (targetWidth < popoverMinWidth ? Position.BOTTOM_LEFT : Position.BOTTOM)}
content={() => (
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Unnecessary new function created every time. Unless we are using the close method we can simply pass the JSX directly

Comment on lines -10 to -12
useIsomorphicLayoutEffect(() => {
ref.current = value
})
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This was unnecessary.

src/table/src/EditableCell.js Show resolved Hide resolved
minWidth: Math.max(width, minWidth),
zIndex
}),
[left, top, height, width, minHeight, minWidth, zIndex]
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think we may want to consider ripping out some of this measurement/dimension logic in favor of a simple hook. There's a lot of complex logic that has nothing to do with this component in particular.

Copy link
Contributor

Choose a reason for hiding this comment

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

200% measurement should definitely be a utility hook

Comment on lines +41 to +74
const update = useCallback(() => {
function updater() {
const targetRef = getTargetRef.current()
if (!targetRef) return
tableBodyRef.current = getTableBodyRef(targetRef)

const {
height: targetHeight,
left: targetLeft,
top: targetTop,
width: targetWidth
} = targetRef.getBoundingClientRect()

let calculatedTop
if (tableBodyRef.current) {
const bounds = tableBodyRef.current.getBoundingClientRect()
calculatedTop = Math.min(Math.max(targetTop, bounds.top), bounds.bottom - targetHeight)
} else {
calculatedTop = targetTop
}

setHeight(targetHeight)
setWidth(targetWidth)
setLeft(targetLeft)
setTop(calculatedTop)

// recursively run the updater
latestAnimationFrame.current = requestAnimationFrame(() => updater())
}

// kick off the updater
updater()
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [])
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This could be replaced with a hook – given a ref, we recursively find the dimensions using resize observer. Using resize observer would mean no IE support, but I highly doubt we have great IE support already (and we don't support it in the app).

Copy link
Contributor

Choose a reason for hiding this comment

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

plus the perf on it is likely much better. im in favor of resize observer

@@ -62,6 +64,7 @@ const Avatar = memo(
)

const [imageHasFailedLoading, setImageHasFailedLoading] = useState(false)
const onError = useCallback(() => setImageHasFailedLoading(true), [])
Copy link
Contributor

Choose a reason for hiding this comment

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

this may not be as efficient as one would hope: https://kentcdodds.com/blog/usememo-and-usecallback

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah for sure, might be too aggressive here. I was considering that there is internal state that will cause rerenders, and so we may as well cache the function, but it might be excessive in this case.

src/table/src/EditableCell.js Show resolved Hide resolved
Comment on lines +41 to +74
const update = useCallback(() => {
function updater() {
const targetRef = getTargetRef.current()
if (!targetRef) return
tableBodyRef.current = getTableBodyRef(targetRef)

const {
height: targetHeight,
left: targetLeft,
top: targetTop,
width: targetWidth
} = targetRef.getBoundingClientRect()

let calculatedTop
if (tableBodyRef.current) {
const bounds = tableBodyRef.current.getBoundingClientRect()
calculatedTop = Math.min(Math.max(targetTop, bounds.top), bounds.bottom - targetHeight)
} else {
calculatedTop = targetTop
}

setHeight(targetHeight)
setWidth(targetWidth)
setLeft(targetLeft)
setTop(calculatedTop)

// recursively run the updater
latestAnimationFrame.current = requestAnimationFrame(() => updater())
}

// kick off the updater
updater()
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [])
Copy link
Contributor

Choose a reason for hiding this comment

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

plus the perf on it is likely much better. im in favor of resize observer

minWidth: Math.max(width, minWidth),
zIndex
}),
[left, top, height, width, minHeight, minWidth, zIndex]
Copy link
Contributor

Choose a reason for hiding this comment

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

200% measurement should definitely be a utility hook

@mshwery mshwery merged commit 965735a into master Jul 22, 2021
@mshwery mshwery deleted the performance-tuning branch July 22, 2021 14:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants