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

Prevent searchbar rerender from useRecentSearches #110

Merged
merged 1 commit into from
Apr 14, 2022
Merged

Conversation

yen-tt
Copy link
Contributor

@yen-tt yen-tt commented Apr 13, 2022

SearchBar requires multiple re-renders due to useEffect call in useRecentSearches to setup RecentSearches instance. The changes in this pr ensures a RecentSearches is set on the first render and only re-render if there is an update to recentSearchesLimit.

Findings when attempt to memoize hooks and testing in SearchBar:

Just using useCallback and useMemo doesn't really avoid unnecessary re-renders in our components. By default, the child components will always re-render if the parent component has triggered a render (1). But, this can be override with shouldComponentUpdate for class-based component or with React.memo(SomeComponent) for functional component. React.memo prevents unnecessary re-renders if there's no change in the props (and no state update in the component itself), and we can use useMemo/useCallback to avoid creating new object when passing props to component each time.

I attempted to use React.memo on DropdownInput for SearchBar (had to wrap a lot of things in useCallback), but there's a lot of props and state changes from SearchBar interactions that almost certainly would require a re-render of the subcomponents. Clicking in/out of searchbar, typing/submitting/clearing inputs in some way generally trigger some setState functions due to new results and/or make updates to the different contexts that would affect the Dropdown components. Additionally, some advise that components like Dropdown with child prop shouldn't use React.memo since the children prop almost always changes.

I believe there may not be a lot of benefits for doing useCallback throughout SearchBar to avoid re-renders in its subcomponents. It kind of make the codebase more complicated with the overhead and less readable, unless there's an actual performance bottleneck to address. So I'm a bit hesitant to add more useMemo/useCallback in our hooks and components if we don't need to.

J=SLAP-1965
TEST=manual

log number of renders in SearchBar before and after useRecentSearch changes. See that SearchBar have less re-renders on initial load.

@yen-tt yen-tt requested a review from a team as a code owner April 13, 2022 20:32
@@ -1,12 +1,18 @@
import { useCallback, useEffect, useState } from 'react';
import { useCallback, useEffect, useRef, useState } from 'react';
Copy link
Contributor

Choose a reason for hiding this comment

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

I think you're right and we'll need to use something like React.memo to get performance benefits from our useCallback/memo usages

Copy link
Contributor

Choose a reason for hiding this comment

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

Oh and I guess I should clarify that I these performance benefits still may or may not be worth it

@yen-tt yen-tt merged commit 5ddba21 into main Apr 14, 2022
@yen-tt yen-tt deleted the dev/memoized-hooks branch April 14, 2022 18:46
yen-tt added a commit that referenced this pull request Sep 28, 2022
…ches (#110)

SearchBar requires multiple re-renders due to useEffect call in useRecentSearches to setup RecentSearches instance. The changes in this pr ensures a RecentSearches is set on the first render and only re-render if there is an update to `recentSearchesLimit`. 

Findings when attempt to memoize hooks and testing in SearchBar:

Just using `useCallback` and `useMemo` doesn't really avoid unnecessary re-renders in our components. By default, the child components will always re-render if the parent component has triggered a render ([1](https://stackoverflow.com/a/40820657)). But, this can be override with shouldComponentUpdate for class-based component or with `React.memo(SomeComponent)` for functional component. `React.memo` prevents unnecessary re-renders if there's no change in the props (and no state update in the component itself), and we can use useMemo/useCallback to avoid creating new object when passing props to component each time.

I attempted to use React.memo on DropdownInput for SearchBar (had to wrap a lot of things in useCallback), but there's a lot of props and state changes from SearchBar interactions that almost certainly would require a re-render of the subcomponents. Clicking in/out of searchbar, typing/submitting/clearing inputs in some way generally trigger some setState functions due to new results and/or make updates to the different contexts that would affect the Dropdown components. Additionally, some advise that components like Dropdown with [child prop shouldn't use React.memo ](facebook/react#14463 (comment) the children prop almost always changes.

I believe there may **not** be a lot of benefits for doing useCallback throughout SearchBar to avoid re-renders in its subcomponents. It kind of make the codebase more complicated with the overhead and less readable, unless there's an actual performance bottleneck to address. So I'm a bit hesitant to add more useMemo/useCallback in our hooks and components if we don't need to.

J=SLAP-1965
TEST=manual

log number of renders in SearchBar before and after useRecentSearch changes. See that SearchBar have less re-renders on initial load.
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.

2 participants