Skip to content

Commit 906e7dd

Browse files
authored
Merge pull request #1336 from thunderstore-io/02-21-fix_packagesearch_page_not_resetting_when_changing_filters
Fix PackageSearch page not resetting when changing filters
2 parents ea130e8 + 2877eb9 commit 906e7dd

File tree

2 files changed

+160
-104
lines changed

2 files changed

+160
-104
lines changed

apps/cyberstorm-remix/app/commonComponents/PackageSearch/PackageSearch.tsx

Lines changed: 158 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,8 @@ interface Props {
4444
}
4545

4646
type SearchParamsType = {
47-
order?: PackageOrderOptionsType;
47+
search: string;
48+
order: PackageOrderOptionsType | undefined;
4849
section: string;
4950
deprecated: boolean;
5051
nsfw: boolean;
@@ -60,15 +61,13 @@ export function PackageSearch(props: Props) {
6061
const { listings, packageCategories: allCategories, sections } = props;
6162
const allSections = sections.sort((a, b) => a.priority - b.priority);
6263

63-
// const [searchParams, setSearchParams] = useSearchParams();
6464
const navigation = useNavigation();
6565

66-
// REMIX START
67-
6866
const navigationType = useNavigationType();
6967

7068
const [searchParams, setSearchParams] = useSearchParams();
7169

70+
const initialSearch = searchParams.getAll("search").join(" ");
7271
const initialOrder = searchParams.get("ordering");
7372
const initialSection = searchParams.get("section");
7473
const initialDeprecated = searchParams.get("deprecated");
@@ -77,7 +76,8 @@ export function PackageSearch(props: Props) {
7776
const initialIncludedCategories = searchParams.get("includedCategories");
7877
const initialExcludedCategories = searchParams.get("excludedCategories");
7978

80-
const [searchParamsBlob, setSearchParamsBlob] = useState<SearchParamsType>({
79+
const initialParams = {
80+
search: initialSearch,
8181
order:
8282
initialOrder && isPackageOrderOptions(initialOrder)
8383
? (initialOrder as PackageOrderOptionsType)
@@ -110,42 +110,24 @@ export function PackageSearch(props: Props) {
110110
initialIncludedCategories !== null ? initialIncludedCategories : "",
111111
excludedCategories:
112112
initialExcludedCategories !== null ? initialExcludedCategories : "",
113-
});
114-
115-
// TODO: Disabled until we can figure out how a proper way to display skeletons
116-
// const navigation = useNavigation();
117-
118-
// Order start
119-
const changeOrder = (v: PackageOrderOptionsType) => {
120-
setSearchParamsBlob({ ...searchParamsBlob, order: v });
121113
};
122-
// Order end
123114

124-
// Search start
125-
const [searchValue, setSearchValue] = useState(
126-
searchParams.getAll("search").join(" ")
127-
);
115+
// Note: Ensure that page is reset to 1 on each setSearchParamsBlob call
116+
const [searchParamsBlob, setSearchParamsBlob] =
117+
useState<SearchParamsType>(initialParams);
128118

129-
useEffect(() => {
130-
if (navigationType === "POP") {
131-
setSearchValue(searchParams.getAll("search").join(" "));
132-
}
133-
}, [searchParams]);
134-
135-
const [debouncedSearchValue] = useDebounce(searchValue, 300, {
136-
maxWait: 300,
137-
});
119+
const [currentPage, setCurrentPage] = useState(
120+
initialPage &&
121+
!Number.isNaN(Number.parseInt(initialPage)) &&
122+
Number.isSafeInteger(Number.parseInt(initialPage))
123+
? Number.parseInt(initialPage)
124+
: 1
125+
);
138126

139-
useEffect(() => {
140-
if (debouncedSearchValue === "") {
141-
searchParams.delete("search");
142-
setSearchParams(searchParams, { replace: true });
143-
} else {
144-
searchParams.set("search", debouncedSearchValue);
145-
setSearchParams(searchParams, { replace: true });
146-
}
147-
}, [debouncedSearchValue]);
148-
// Search end
127+
// Setters
128+
const setSearch = (v: string) => {
129+
setSearchParamsBlob({ ...searchParamsBlob, search: v });
130+
};
149131

150132
const setSection = (v: string) => {
151133
setSearchParamsBlob({ ...searchParamsBlob, section: v });
@@ -163,6 +145,17 @@ export function PackageSearch(props: Props) {
163145
setSearchParamsBlob({ ...searchParamsBlob, page: v });
164146
};
165147

148+
const setOrder = (v: PackageOrderOptionsType) => {
149+
setSearchParamsBlob({ ...searchParamsBlob, order: v });
150+
};
151+
152+
// Grab params and insert into useStated states
153+
useEffect(() => {
154+
if (navigationType === "POP") {
155+
setSearch(searchParams.getAll("search").join(" "));
156+
}
157+
}, [searchParams]);
158+
166159
// Categories start
167160
const categories: CategorySelection[] = allCategories
168161
.sort((a, b) => a.slug.localeCompare(b.slug))
@@ -186,12 +179,14 @@ export function PackageSearch(props: Props) {
186179
} else {
187180
newSearchParams.excludedCategories = excludedCategories.join(",");
188181
}
189-
setSearchParamsBlob(newSearchParams);
182+
setSearchParamsBlob({ ...newSearchParams });
190183
};
184+
191185
// Categories end
192186

193-
const resetParams = (order?: PackageOrderOptionsType) => {
187+
const resetParams = (order: PackageOrderOptionsType | undefined) => {
194188
setSearchParamsBlob({
189+
search: "",
195190
order: order,
196191
section: allSections.length === 0 ? "" : allSections[0]?.uuid,
197192
deprecated: false,
@@ -200,69 +195,137 @@ export function PackageSearch(props: Props) {
200195
includedCategories: "",
201196
excludedCategories: "",
202197
});
203-
setSearchValue("");
198+
// setOrdering(order);
199+
// setPage(1);
200+
// setSearchValue("");
204201
};
205202

206-
const [debouncedSearchParamsBlob] = useDebounce(searchParamsBlob, 750, {
207-
maxWait: 750,
203+
const clearAll = () =>
204+
setSearchParamsBlob({
205+
...searchParamsBlob,
206+
search: "",
207+
includedCategories: "",
208+
excludedCategories: "",
209+
});
210+
211+
const [debouncedSearchParamsBlob] = useDebounce(searchParamsBlob, 300, {
212+
maxWait: 300,
208213
});
209214

210215
useEffect(() => {
216+
let useReplace = false;
217+
let resetPage = false;
218+
const oldSearch = searchParams.getAll("search").join(" ");
219+
const oldOrdering = searchParams.get("ordering") ?? undefined;
220+
const oldSection = searchParams.get("section") ?? "";
221+
const oldDeprecated = searchParams.get("deprecated") ? true : false;
222+
const oldNSFW = searchParams.get("nsfw") ? true : false;
223+
const oldIncludedCategories = searchParams.get("includedCategories") ?? "";
224+
const oldExcludedCategories = searchParams.get("excludedCategories") ?? "";
225+
const oldPage = searchParams.get("page")
226+
? Number(searchParams.get("page"))
227+
: 1;
228+
229+
// Search
230+
if (oldSearch !== debouncedSearchParamsBlob.search) {
231+
if (debouncedSearchParamsBlob.search === "") {
232+
searchParams.delete("search");
233+
} else {
234+
searchParams.set("search", debouncedSearchParamsBlob.search);
235+
}
236+
resetPage = true;
237+
useReplace = true;
238+
}
211239
// Order
212-
if (
213-
debouncedSearchParamsBlob.order === undefined ||
214-
debouncedSearchParamsBlob.order === PackageOrderOptions.Updated
215-
) {
216-
searchParams.delete("ordering");
217-
} else {
218-
searchParams.set("ordering", debouncedSearchParamsBlob.order);
240+
if (oldOrdering !== debouncedSearchParamsBlob.order) {
241+
if (
242+
debouncedSearchParamsBlob.order === undefined ||
243+
debouncedSearchParamsBlob.order === PackageOrderOptions.Updated
244+
) {
245+
searchParams.delete("ordering");
246+
} else {
247+
searchParams.set("ordering", debouncedSearchParamsBlob.order);
248+
}
249+
resetPage = true;
219250
}
220251
// Section
221-
if (
222-
allSections.length === 0 ||
223-
debouncedSearchParamsBlob.section === allSections[0]?.uuid ||
224-
debouncedSearchParamsBlob.section === ""
225-
) {
226-
searchParams.delete("section");
227-
} else {
228-
searchParams.set("section", debouncedSearchParamsBlob.section);
252+
if (oldSection !== debouncedSearchParamsBlob.section) {
253+
if (
254+
allSections.length === 0 ||
255+
debouncedSearchParamsBlob.section === allSections[0]?.uuid ||
256+
debouncedSearchParamsBlob.section === ""
257+
) {
258+
searchParams.delete("section");
259+
} else {
260+
searchParams.set("section", debouncedSearchParamsBlob.section);
261+
}
262+
resetPage = true;
229263
}
230264
// Deprecated
231-
if (debouncedSearchParamsBlob.deprecated === false) {
232-
searchParams.delete("deprecated");
233-
} else {
234-
searchParams.set("deprecated", "true");
265+
if (oldDeprecated !== debouncedSearchParamsBlob.deprecated) {
266+
if (debouncedSearchParamsBlob.deprecated === false) {
267+
searchParams.delete("deprecated");
268+
} else {
269+
searchParams.set("deprecated", "true");
270+
}
271+
resetPage = true;
235272
}
236273
// NSFW
237-
if (debouncedSearchParamsBlob.nsfw === false) {
238-
searchParams.delete("nsfw");
239-
} else {
240-
searchParams.set("nsfw", "true");
241-
}
242-
// Page number
243-
if (debouncedSearchParamsBlob.page === 1) {
244-
searchParams.delete("page");
245-
} else {
246-
searchParams.set("page", String(debouncedSearchParamsBlob.page));
274+
if (oldNSFW !== debouncedSearchParamsBlob.nsfw) {
275+
if (debouncedSearchParamsBlob.nsfw === false) {
276+
searchParams.delete("nsfw");
277+
} else {
278+
searchParams.set("nsfw", "true");
279+
}
280+
resetPage = true;
247281
}
248282
// Categories
249-
if (debouncedSearchParamsBlob.includedCategories === "") {
250-
searchParams.delete("includedCategories");
283+
if (
284+
oldIncludedCategories !== debouncedSearchParamsBlob.includedCategories
285+
) {
286+
if (debouncedSearchParamsBlob.includedCategories === "") {
287+
searchParams.delete("includedCategories");
288+
} else {
289+
searchParams.set(
290+
"includedCategories",
291+
debouncedSearchParamsBlob.includedCategories
292+
);
293+
}
294+
resetPage = true;
295+
}
296+
if (
297+
oldExcludedCategories !== debouncedSearchParamsBlob.excludedCategories
298+
) {
299+
if (debouncedSearchParamsBlob.excludedCategories === "") {
300+
searchParams.delete("excludedCategories");
301+
} else {
302+
searchParams.set(
303+
"excludedCategories",
304+
debouncedSearchParamsBlob.excludedCategories
305+
);
306+
}
307+
resetPage = true;
308+
}
309+
// Page number
310+
if (oldPage !== debouncedSearchParamsBlob.page) {
311+
if (debouncedSearchParamsBlob.page === 1 || resetPage) {
312+
searchParams.delete("page");
313+
setCurrentPage(1);
314+
} else {
315+
searchParams.set("page", String(debouncedSearchParamsBlob.page));
316+
setCurrentPage(debouncedSearchParamsBlob.page);
317+
}
251318
} else {
252-
searchParams.set(
253-
"includedCategories",
254-
debouncedSearchParamsBlob.includedCategories
255-
);
319+
if (resetPage) {
320+
searchParams.delete("page");
321+
setCurrentPage(1);
322+
}
256323
}
257-
if (debouncedSearchParamsBlob.excludedCategories === "") {
258-
searchParams.delete("excludedCategories");
324+
if (useReplace) {
325+
setSearchParams(searchParams, { replace: true });
259326
} else {
260-
searchParams.set(
261-
"excludedCategories",
262-
debouncedSearchParamsBlob.excludedCategories
263-
);
327+
setSearchParams(searchParams);
264328
}
265-
setSearchParams(searchParams);
266329
}, [debouncedSearchParamsBlob]);
267330

268331
function parseCategories(
@@ -316,9 +379,9 @@ export function PackageSearch(props: Props) {
316379
<div className="package-search__sidebar">
317380
<NewTextInput
318381
placeholder="Search Mods..."
319-
value={searchValue}
320-
onChange={(e) => setSearchValue(e.target.value)}
321-
clearValue={() => setSearchValue("")}
382+
value={searchParamsBlob.search}
383+
onChange={(e) => setSearch(e.target.value)}
384+
clearValue={() => setSearch("")}
322385
leftIcon={<FontAwesomeIcon icon={faSearch} />}
323386
id="searchInput"
324387
type="search"
@@ -383,33 +446,31 @@ export function PackageSearch(props: Props) {
383446
<div className="package-search__content">
384447
<div className="package-search__search-params">
385448
<CategoryTagCloud
386-
searchValue={searchValue}
387-
setSearchValue={setSearchValue}
449+
searchValue={searchParamsBlob.search}
450+
setSearchValue={setSearch}
388451
categories={parseCategories(
389452
searchParamsBlob.includedCategories ?? "",
390453
searchParamsBlob.excludedCategories ?? ""
391454
)}
392455
setCategories={setCategories}
393456
rootClasses="package-search__tags"
457+
clearAll={clearAll}
394458
/>
395459
<div className="package-search__tools">
396460
<div className="package-search__results">
397461
<PackageCount
398-
page={searchParamsBlob.page ? Number(searchParamsBlob.page) : 1}
462+
page={currentPage}
399463
pageSize={PER_PAGE}
400-
searchQuery={debouncedSearchValue}
464+
searchQuery={searchParamsBlob.search}
401465
totalCount={listings.count}
402466
/>
403467
</div>
404468
<div className="package-search__listing-actions">
405469
{/* <div className="__display"></div> */}
406470
<div className="package-search__sorting">
407471
<PackageOrder
408-
order={
409-
(searchParamsBlob.order as PackageOrderOptions) ??
410-
PackageOrderOptions.Updated
411-
}
412-
setOrder={changeOrder}
472+
order={searchParamsBlob.order ?? PackageOrderOptions.Updated}
473+
setOrder={setOrder}
413474
/>
414475
</div>
415476
</div>
@@ -461,9 +522,7 @@ export function PackageSearch(props: Props) {
461522
</StalenessIndicator>
462523
<div className="package-search__pagination">
463524
<NewPagination
464-
currentPage={
465-
searchParamsBlob.page ? Number(searchParamsBlob.page) : 1
466-
}
525+
currentPage={currentPage}
467526
onPageChange={setPage}
468527
pageSize={PER_PAGE}
469528
siblingCount={4}

0 commit comments

Comments
 (0)