Skip to content

Commit c67e1d5

Browse files
author
Dominik Schröder
committed
debounce search
1 parent 62ace20 commit c67e1d5

File tree

4 files changed

+86
-12
lines changed

4 files changed

+86
-12
lines changed

src/components/Drawer.tsx

+63-3
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@
22
import {
33
useRef,
44
useState,
5+
useCallback,
56
useEffect,
67
type ReactElement,
8+
use,
79
} from "react";
810

911
import {
@@ -207,13 +209,71 @@ export function MultiSelect({
207209
);
208210
}
209211

212+
function debounce<T>(
213+
func: (...param: T[]) => void,
214+
timeout = 3000
215+
) {
216+
let timer: number;
217+
218+
return (...args: T[]) => {
219+
window.clearTimeout(timer);
220+
timer = window.setTimeout(func, timeout, ...args);
221+
};
222+
}
223+
224+
const TextFieldDebounced: React.FC<{
225+
debounceMs?: number;
226+
onChange: (p: string) => void;
227+
value: string;
228+
}> = ({debounceMs = 300, onChange, value = ""}) => {
229+
const debouncedChangeHandler = useCallback(
230+
debounce(onChange, debounceMs),
231+
[]
232+
);
233+
234+
const handleChange = ({
235+
target,
236+
}: React.ChangeEvent<HTMLInputElement>) => {
237+
debouncedChangeHandler(target.value);
238+
};
239+
240+
return (
241+
<TextField value={value} onChange={handleChange} />
242+
);
243+
};
244+
245+
const useDebounce = (value: string, delay = 500) => {
246+
const [debouncedValue, setDebouncedValue] = useState("");
247+
const timerRef = useRef<NodeJS.Timeout | null>();
248+
249+
useEffect(() => {
250+
timerRef.current = setTimeout(
251+
() => setDebouncedValue(value),
252+
delay
253+
);
254+
255+
return () => {
256+
if (timerRef.current !== null)
257+
clearTimeout(timerRef.current);
258+
};
259+
}, [value, delay]);
260+
261+
return debouncedValue;
262+
};
263+
210264
export function SearchBox() {
211265
const [openSearch, setOpenSearch] = useState(false);
212266
const {search, setSearch} = useStore((state) => ({
213267
search: state.search,
214268
setSearch: state.setSearch,
215269
}));
216270

271+
const [text, setText] = useState(search);
272+
const debouncedSearch = useDebounce(text, 300);
273+
useEffect(() => {
274+
setSearch(debouncedSearch);
275+
}, [debouncedSearch]);
276+
217277
return (
218278
<SidebarButton
219279
contentOpen={openSearch}
@@ -240,10 +300,10 @@ export function SearchBox() {
240300
sx={{width: "200px", mr: 1, mt: 0.5}}
241301
margin="none"
242302
size="small"
243-
label="Activity Title"
244-
value={search}
303+
label="Title/Description"
304+
value={text}
245305
onChange={(event) => {
246-
setSearch(event.target.value);
306+
setText(event.target.value);
247307
}}
248308
/>
249309
</SidebarButton>

src/components/Header.tsx

+16-9
Original file line numberDiff line numberDiff line change
@@ -60,14 +60,21 @@ const tabs = {
6060
};
6161

6262
export default function Header() {
63-
const {open, setOpen, activeStatsTab, user, guest} =
64-
useStore((state) => ({
65-
open: state.drawerOpen,
66-
setOpen: state.toggleDrawer,
67-
activeStatsTab: state.activeStatsTab,
68-
user: state.user,
69-
guest: state.guest,
70-
}));
63+
const {
64+
open,
65+
setOpen,
66+
activeStatsTab,
67+
user,
68+
guest,
69+
loading,
70+
} = useStore((state) => ({
71+
open: state.drawerOpen,
72+
setOpen: state.toggleDrawer,
73+
activeStatsTab: state.activeStatsTab,
74+
user: state.user,
75+
guest: state.guest,
76+
loading: state.loading,
77+
}));
7178
const pathname = usePathname();
7279
const parts = pathname.split("/");
7380
const valueKey = parts.length > 1 ? `/${parts[1]}` : "";
@@ -161,7 +168,7 @@ export default function Header() {
161168
<UserSettings user={user} />
162169
</>
163170
)}{" "}
164-
{!user && !guest && <LoginButton />}
171+
{!user && !guest && !loading && <LoginButton />}
165172
</Toolbar>
166173
</AppBar>
167174
);

src/components/MainContainer.tsx

+4
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ export default function MainContainer({
2121
toggleUserSettings,
2222
setUser,
2323
setGuest,
24+
setLoading,
2425
} = useStore((state) => ({
2526
loadFromDB: state.loadFromDB,
2627
updateFilters: state.updateFilters,
@@ -29,6 +30,7 @@ export default function MainContainer({
2930
loadPhotos: state.loadPhotos,
3031
setUser: state.setUser,
3132
setGuest: state.setGuest,
33+
setLoading: state.setLoading,
3234
}));
3335

3436
const searchParams = useSearchParams();
@@ -63,6 +65,8 @@ export default function MainContainer({
6365
load(activities)
6466
.then(console.log)
6567
.catch(console.error);
68+
} else {
69+
setLoading(false);
6670
}
6771

6872
async function load(activities?: number[]) {

src/contexts/Filter.ts

+3
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,9 @@ export const filterSlice: StateCreator<
133133
state.search &&
134134
!row.name
135135
.toLowerCase()
136+
.includes(state.search.toLowerCase()) &&
137+
!row.description
138+
?.toLowerCase()
136139
.includes(state.search.toLowerCase())
137140
) {
138141
return false;

0 commit comments

Comments
 (0)