Skip to content

Commit 679eacf

Browse files
committed
perf: filter application
1 parent e02bcce commit 679eacf

2 files changed

Lines changed: 56 additions & 62 deletions

File tree

src/components/CatalogueContent.tsx

Lines changed: 49 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ const CatalogueContentInner = ({ subject }: { subject: string | null }) => {
122122
localStorage.setItem("userSubjects", JSON.stringify(updated));
123123
};
124124

125-
// Fetch papers and apply filters
125+
// Fetch papers ONLY when subject changes (not when filters change!)
126126
useEffect(() => {
127127
if (!subject || !isMounted) return;
128128

@@ -136,36 +136,6 @@ const CatalogueContentInner = ({ subject }: { subject: string | null }) => {
136136
const papersData = data.papers;
137137
setFilterOptions(data);
138138
setPapers(papersData);
139-
const filtered = papersData.filter((paper) => {
140-
const examCondition = selectedExams.length
141-
? selectedExams.includes(paper.exam)
142-
: true;
143-
const slotCondition = selectedSlots.length
144-
? selectedSlots.includes(paper.slot)
145-
: true;
146-
const yearCondition = selectedYears.length
147-
? selectedYears.includes(paper.year)
148-
: true;
149-
const semesterCondition = selectedSemesters.length
150-
? selectedSemesters.includes(paper.semester)
151-
: true;
152-
const campusCondition = selectedCampuses.length
153-
? selectedCampuses.includes(paper.campus)
154-
: true;
155-
const answerkeyCondition = selectedAnswerKeyIncluded
156-
? paper.answer_key_included === true
157-
: true;
158-
return (
159-
examCondition &&
160-
slotCondition &&
161-
yearCondition &&
162-
semesterCondition &&
163-
campusCondition &&
164-
answerkeyCondition
165-
);
166-
});
167-
setFilteredPapers(filtered);
168-
setAppliedFilters(true);
169139
} catch (error) {
170140
setPapers([]);
171141
const axiosError = error as AxiosError;
@@ -184,16 +154,61 @@ const CatalogueContentInner = ({ subject }: { subject: string | null }) => {
184154
}, [
185155
subject,
186156
isMounted,
157+
setPapers,
158+
setFilterOptions,
159+
]);
160+
161+
useEffect(() => {
162+
if (!papers.length) return;
163+
164+
const filtered = papers.filter((paper) => {
165+
const examCondition = selectedExams.length
166+
? selectedExams.includes(paper.exam)
167+
: true;
168+
const slotCondition = selectedSlots.length
169+
? selectedSlots.includes(paper.slot)
170+
: true;
171+
const yearCondition = selectedYears.length
172+
? selectedYears.includes(paper.year)
173+
: true;
174+
const semesterCondition = selectedSemesters.length
175+
? selectedSemesters.includes(paper.semester)
176+
: true;
177+
const campusCondition = selectedCampuses.length
178+
? selectedCampuses.includes(paper.campus)
179+
: true;
180+
const answerkeyCondition = selectedAnswerKeyIncluded
181+
? paper.answer_key_included === true
182+
: true;
183+
return (
184+
examCondition &&
185+
slotCondition &&
186+
yearCondition &&
187+
semesterCondition &&
188+
campusCondition &&
189+
answerkeyCondition
190+
);
191+
});
192+
193+
setFilteredPapers(filtered);
194+
setAppliedFilters(
195+
selectedExams.length > 0 ||
196+
selectedSlots.length > 0 ||
197+
selectedYears.length > 0 ||
198+
selectedSemesters.length > 0 ||
199+
selectedCampuses.length > 0 ||
200+
selectedAnswerKeyIncluded
201+
);
202+
}, [
203+
papers,
187204
selectedExams,
188205
selectedSlots,
189206
selectedYears,
190207
selectedSemesters,
191208
selectedCampuses,
192209
selectedAnswerKeyIncluded,
193-
setPapers,
194-
setFilterOptions,
195-
setAppliedFilters,
196210
setFilteredPapers,
211+
setAppliedFilters,
197212
]);
198213

199214
// Render loading state until mounted to avoid hydration mismatch

src/context/filterContext.tsx

Lines changed: 7 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -169,8 +169,7 @@ export const FilterProvider: React.FC<FilterProviderProps> = ({ children, subjec
169169
semester: string[],
170170
anskey: boolean,
171171
) => {
172-
setAppliedFilters(true);
173-
172+
// Update URL for bookmarking/sharing (use replace to avoid navigation/re-fetch)
174173
let pushContent = "/catalogue";
175174
if (subject) pushContent += `?subject=${encodeURIComponent(subject)}`;
176175
if (exams.length > 0)
@@ -185,39 +184,19 @@ export const FilterProvider: React.FC<FilterProviderProps> = ({ children, subjec
185184
pushContent += `&semester=${encodeURIComponent(semester.join(","))}`;
186185
if (anskey) pushContent += "&answerkey=true";
187186

188-
router.push(pushContent);
187+
// Use replace instead of push to avoid triggering navigation/re-render
188+
router.replace(pushContent, { scroll: false });
189+
190+
// Update filter state (filtering happens in useEffect in CatalogueContent)
189191
setSelectedExams(exams);
190192
setSelectedSlots(slots);
191193
setSelectedYears(years);
192194
setSelectedCampuses(campus);
193195
setSelectedSemesters(semester);
194196
setSelectedAnswerKeyIncluded(anskey);
195-
196-
const filtered = papers.filter((paper) => {
197-
const examCondition = exams.length ? exams.includes(paper.exam) : true;
198-
const slotCondition = slots.length ? slots.includes(paper.slot) : true;
199-
const yearCondition = years.length ? years.includes(paper.year) : true;
200-
const campusCondition = campus.length
201-
? campus.includes(paper.campus)
202-
: true;
203-
const semesterCondition = semester.length
204-
? semester.includes(paper.semester)
205-
: true;
206-
const anskeyCondition = anskey ? paper.answer_key_included === true : true;
207-
208-
return (
209-
examCondition &&
210-
slotCondition &&
211-
yearCondition &&
212-
campusCondition &&
213-
semesterCondition &&
214-
anskeyCondition
215-
);
216-
});
217-
setFilteredPapers(filtered);
218-
setCurrentPage(1);
197+
setCurrentPage(1); // Reset to first page when filters change
219198
},
220-
[papers, router, subject],
199+
[router, subject, setSelectedExams, setSelectedSlots, setSelectedYears, setSelectedCampuses, setSelectedSemesters, setSelectedAnswerKeyIncluded, setCurrentPage],
221200
);
222201

223202

0 commit comments

Comments
 (0)