Skip to content

Commit f8c5871

Browse files
committed
fix search
1 parent 8adabf6 commit f8c5871

File tree

2 files changed

+31
-11
lines changed

2 files changed

+31
-11
lines changed

web/src/components/Lists.tsx

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React, { useRef } from "react";
1+
import React, { useLayoutEffect, useRef, useState } from "react";
22
import { useWindowVirtualizer } from "@tanstack/react-virtual";
33

44
interface Props<T> {
@@ -9,12 +9,19 @@ interface Props<T> {
99

1010
export function LazyList<T>({ className, data, render }: Props<T>) {
1111
const listRef = useRef<HTMLDivElement>(null);
12+
const [scrollMargin, setScrollMargin] = useState(0);
13+
14+
useLayoutEffect(() => {
15+
if (listRef.current) {
16+
setScrollMargin(listRef.current.offsetTop);
17+
}
18+
}, []);
1219

1320
const virtualizer = useWindowVirtualizer({
1421
count: data.length,
1522
estimateSize: () => 200,
16-
overscan: 3,
17-
scrollMargin: listRef.current?.offsetTop ?? 0,
23+
overscan: 10,
24+
scrollMargin,
1825
});
1926

2027
return (
@@ -30,7 +37,7 @@ export function LazyList<T>({ className, data, render }: Props<T>) {
3037
top: 0,
3138
left: 0,
3239
width: "100%",
33-
transform: `translateY(${virtualRow.start - virtualizer.options.scrollMargin}px)`,
40+
transform: `translateY(${virtualRow.start - scrollMargin}px)`,
3441
}}
3542
>
3643
{render(data[virtualRow.index])}

web/src/components/Search/index.tsx

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React, { useCallback, useContext, useEffect, useRef } from "react";
1+
import React, { useCallback, useContext, useEffect, useRef, useState } from "react";
22
import { useLocation, useNavigate } from "react-router-dom";
33
import styled from "styled-components";
44
import { SearchContext } from "./SearchContext";
@@ -46,32 +46,45 @@ export const SearchInput = styled.input.attrs({ type: "search" })`
4646

4747
export function SearchBox({ baseUrl, className, placeholder = "Search..." }: { baseUrl: string; className?: string; placeholder?: string }) {
4848
const { search, setSearch } = useContext(SearchContext);
49+
const [inputValue, setInputValue] = useState(search);
4950
const navigate = useNavigate();
5051
const location = useLocation();
5152
const timerRef = useRef<ReturnType<typeof setTimeout>>(undefined);
53+
const pendingRef = useRef(inputValue);
5254

53-
// Sync context from URL (back/forward navigation, clicking links)
55+
// Sync from URL (back/forward navigation, clicking links)
5456
useEffect(() => {
5557
const urlSearch = new URLSearchParams(location.search).get("search") ?? "";
5658
if (urlSearch !== search) {
5759
setSearch(urlSearch);
60+
setInputValue(urlSearch);
61+
pendingRef.current = urlSearch;
5862
}
5963
}, [location.search]); // eslint-disable-line react-hooks/exhaustive-deps
6064

65+
// Sync input when search is set externally (e.g. from programmatic navigation)
66+
useEffect(() => {
67+
setInputValue(search);
68+
pendingRef.current = search;
69+
}, [search]);
70+
6171
// Cleanup debounce timer on unmount
6272
useEffect(() => () => clearTimeout(timerRef.current), []);
6373

6474
const onChange = useCallback<React.ChangeEventHandler<HTMLInputElement>>(
6575
({ target: { value } }) => {
66-
setSearch(value);
76+
setInputValue(value);
77+
pendingRef.current = value;
6778
clearTimeout(timerRef.current);
6879
timerRef.current = setTimeout(() => {
69-
if (value === "") {
80+
const latest = pendingRef.current;
81+
setSearch(latest);
82+
if (latest === "") {
7083
navigate(baseUrl, { replace: true });
7184
} else {
72-
navigate(`${baseUrl}?search=${encodeURIComponent(value)}`, { replace: true });
85+
navigate(`${baseUrl}?search=${encodeURIComponent(latest)}`, { replace: true });
7386
}
74-
}, 300);
87+
}, 150);
7588
},
7689
[setSearch, navigate, baseUrl],
7790
);
@@ -83,7 +96,7 @@ export function SearchBox({ baseUrl, className, placeholder = "Search..." }: { b
8396
className={className}
8497
placeholder={placeholder}
8598
ref={ref}
86-
value={search}
99+
value={inputValue}
87100
onChange={onChange}
88101
aria-label="Search"
89102
/>

0 commit comments

Comments
 (0)