Skip to content

Commit

Permalink
Google Map: Throttle filtering handler to improve performance
Browse files Browse the repository at this point in the history
This can take 5 or more map re-renders and condense it down to 1, without a noticible effect on responsiveness to the user.

See https://www.developerway.com/posts/debouncing-in-react
  • Loading branch information
iandunn committed Oct 13, 2023
1 parent 2d1fb84 commit 6456a77
Showing 1 changed file with 35 additions and 12 deletions.
47 changes: 35 additions & 12 deletions mu-plugins/blocks/google-map/src/components/main.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
/**
* External dependencies
*/
import { throttle } from 'lodash';

/**
* WordPress dependencies
*/
import { useCallback, useEffect, useRef, useState } from '@wordpress/element';
import { useCallback, useMemo, useRef, useState } from '@wordpress/element';
import { __, sprintf } from '@wordpress/i18n';

/**
Expand Down Expand Up @@ -61,24 +66,42 @@ export default function Main( {
inline: 'start',
behavior: 'smooth',
} );

// This is passing the value directly, instead of using, state because the throttled function only has
// access to the versionof state that existed at the time the function was created. Updating the
// function with something like `useCallback` is more complicated than you'd think.
throttledRedrawMap( event.target.value );
}, [] );

/**
* Update the map and list when the search query changes.
* Redraw the map and list based on the user's search query.
*/
useEffect( () => {
const filteredMarkers = filterMarkers( validMarkers, searchQuery, searchFields );
const redrawMap = useCallback(
( newSearchQuery ) => {
const filteredMarkers = filterMarkers( validMarkers, newSearchQuery, searchFields );

setVisibleMarkers( filteredMarkers );
setVisibleMarkers( filteredMarkers );

// Avoid speaking on the initial page load.
if ( ! searchQueryInitialized.current ) {
searchQueryInitialized.current = true;
return;
}
// Avoid speaking on the initial page load.
if ( ! searchQueryInitialized.current ) {
searchQueryInitialized.current = true;
return;
}

speakSearchUpdates( searchQuery, filteredMarkers.length );
}, [ searchQuery ] );
speakSearchUpdates( newSearchQuery, filteredMarkers.length );
},
[ validMarkers, searchFields ]
);

/**
* Throttle the redraw function so it doesn't do expensive operations that the user won't notice.
*/
const throttledRedrawMap = useMemo( () => {
return throttle( redrawMap, 200, {
leading: false,
trailing: true,
} );
}, [ redrawMap ] );

return (
<>
Expand Down

0 comments on commit 6456a77

Please sign in to comment.