-
Notifications
You must be signed in to change notification settings - Fork 2.7k
MM-35509 Do not use getDerivedStateFromProps to determine picker placement and instead use memoization #8092
Conversation
… instead use memoization
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'm not sure this would help, if function getBoundingRect
is the culprit and is being called twice with the same target, wouldn't it be better to wrap and only memoize target.getBoundingRect
?
if you memoize the parent call you'd still be calling getBoundingRect
twice as they are two different functions.
so something like this might be enough to alleviate the double call:
const getTargetRect = memoize((target) => target.getBoundingRect());
my only concern with that approach is that I'm not entirely sure what target is but most likely an object, if that's the case we'll need to do a custom equality function based on the object to figure out when two call should yield the same result.
edit: digging a bit deeper, seems the overlay is called with a function that returns a reactRef which I think it uses the htmldivelement
type. If so we can probably use isSameNode or isEqualNode to do a proper comparison.
edit 2: at least one of the calls is still using a stringRef
instead of createRef
, since we havent yet finished the migration campaign, so in order for this to work we would need to migrate edit_post_modal.jsx
as well
Co-authored-by: Guillermo Vayá <[email protected]>
Thanks for the feedback @Willyfrog
This helps because before this change on every single character typed I'm not too worried about the double call when we do actually render, though your code would be a further improvement to prevent that.
Are we sure a strict comparison is not enough? If the React node is re-created and the ref points to a new node does the value not change? Can that even happen in this case without the EmojiPickerOverlay also being re-created? |
@jgilliam17 for testing we just need to make sure that all the places the Emoji Picker can open, it does so the same as it did before (e.g. which placement it has). |
I agree with this, I was mostly answering on your initial comment about it being called multiple times, but I didn't check where it was being called 👍
A strict comparison would also work (it won't work with the default comparison from memoize as the author says it is a shallow one), but if the object already provides a comparison method I usually prefer to trust the one who created object as a better/more efficient way. anyways, I'll aprove the change 😄 |
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.
Nice analysis, @jwilander! Seems like as solid change, even if we can't tie it directly to the performance issues.
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 @jwilander
Tested, looks good to merge.
- Verified Emoji Picker placement when opening in main channel text box, edit post, on RHS etc.
Test server destroyed |
Cherry pick is scheduled. |
…ement and instead use memoization (mattermost#8092) * Do not use getDerivedStateFromProps to determine picker placement and instead use memoization * Update components/emoji_picker/emoji_picker_overlay.jsx Co-authored-by: Guillermo Vayá <[email protected]> * Lint fixes Co-authored-by: Guillermo Vayá <[email protected]> (cherry picked from commit 692f907)
…ement and instead use memoization (#8092) (#8099) * Do not use getDerivedStateFromProps to determine picker placement and instead use memoization * Update components/emoji_picker/emoji_picker_overlay.jsx Co-authored-by: Guillermo Vayá <[email protected]> * Lint fixes Co-authored-by: Guillermo Vayá <[email protected]> (cherry picked from commit 692f907) Co-authored-by: Joram Wilander <[email protected]>
/cherry-pick release-5.35 |
Cherry pick is scheduled. |
…ement and instead use memoization (mattermost#8092) * Do not use getDerivedStateFromProps to determine picker placement and instead use memoization * Update components/emoji_picker/emoji_picker_overlay.jsx Co-authored-by: Guillermo Vayá <[email protected]> * Lint fixes Co-authored-by: Guillermo Vayá <[email protected]> (cherry picked from commit 692f907)
…ement and instead use memoization (#8092) (#8212) * Do not use getDerivedStateFromProps to determine picker placement and instead use memoization * Update components/emoji_picker/emoji_picker_overlay.jsx Co-authored-by: Guillermo Vayá <[email protected]> * Lint fixes Co-authored-by: Guillermo Vayá <[email protected]> (cherry picked from commit 692f907) Co-authored-by: Joram Wilander <[email protected]>
Summary
A customer is experiencing slow typing issues. A JS profile showed the following:
A very significant amount of time is spent on "Recalculate Style" and the primary trigger for this seems to be the
getBoundingClientRect
function calls inside the EmojiPickerOverlay component. After some brief investigation it was apparent that on every single character typed into the textboxgetBoundingClientRect
was being called twice due to improper use ofgetDerivedStateFromProps
. I have used memoization to properly implement the functionality in a much more performant way.Unfortunately, I was unable to reproduce the exact slow typing issue the customer is experiencing so I'm not sure how much effect this will have or if this is the root cause of the issues or not.
Ticket Link
https://mattermost.atlassian.net/browse/MM-35509
Release Note