Skip to content

Commit e977d8e

Browse files
committed
fix: Switch UserAutocomplete to useDebouncedFunction
1 parent fcc8b9e commit e977d8e

File tree

1 file changed

+24
-10
lines changed

1 file changed

+24
-10
lines changed

site/src/components/UserAutocomplete/UserAutocomplete.tsx

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,17 @@ import { useMachine } from "@xstate/react";
66
import { User } from "api/typesGenerated";
77
import { Avatar } from "components/Avatar/Avatar";
88
import { AvatarData } from "components/AvatarData/AvatarData";
9-
import debounce from "just-debounce-it";
10-
import { ChangeEvent, ComponentProps, FC, useEffect, useState } from "react";
9+
import {
10+
ChangeEvent,
11+
ComponentProps,
12+
FC,
13+
useEffect,
14+
useRef,
15+
useState,
16+
} from "react";
1117
import { searchUserMachine } from "xServices/users/searchUserXService";
1218
import Box from "@mui/material/Box";
19+
import { useDebouncedFunction } from "hooks/debounce";
1320

1421
export type UserAutocompleteProps = {
1522
value: User | null;
@@ -31,16 +38,23 @@ export const UserAutocomplete: FC<UserAutocompleteProps> = ({
3138
const [searchState, sendSearch] = useMachine(searchUserMachine);
3239
const { searchResults } = searchState.context;
3340

34-
// seed list of options on the first page load if a user pases in a value
35-
// since some organizations have long lists of users, we do not load all options on page load.
41+
// seed list of options on the first page load if a user passes in a value
42+
// since some organizations have long lists of users, we do not load all
43+
// options on page load.
44+
const onMountRef = useRef(value);
3645
useEffect(() => {
37-
if (value) {
38-
sendSearch("SEARCH", { query: value.email });
46+
const mountValue = onMountRef.current;
47+
if (mountValue) {
48+
sendSearch("SEARCH", { query: mountValue.email });
3949
}
40-
// eslint-disable-next-line react-hooks/exhaustive-deps -- TODO look into this
41-
}, []);
4250

43-
const handleFilterChange = debounce(
51+
// 2023-09-15 - This isn't in XState's docs, but its source code guarantees
52+
// that the memory reference of sendSearch will stay stable across renders.
53+
// This useEffect call will behave like an on-mount effect and will not ever
54+
// need to resynchronize
55+
}, [sendSearch]);
56+
57+
const { debounced: debouncedOnChange } = useDebouncedFunction(
4458
(event: ChangeEvent<HTMLInputElement>) => {
4559
sendSearch("SEARCH", { query: event.target.value });
4660
},
@@ -93,7 +107,7 @@ export const UserAutocomplete: FC<UserAutocompleteProps> = ({
93107
className={styles.textField}
94108
InputProps={{
95109
...params.InputProps,
96-
onChange: handleFilterChange,
110+
onChange: debouncedOnChange,
97111
startAdornment: value && (
98112
<Avatar size="sm" src={value.avatar_url}>
99113
{value.username}

0 commit comments

Comments
 (0)