Skip to content

Commit 5363800

Browse files
authored
refactor(hooks): export MAX_SEARCHES and STORAGE_KEY constants (JhaSourav07#476)
## Description Fixes JhaSourav07#394 ## Pillar - [ ] 🎨 Pillar 1 β€” New Theme Design - [ ] πŸ“ Pillar 2 β€” Geometric SVG Improvement - [ ] πŸ• Pillar 3 β€” Timezone Logic Optimization - [x] πŸ› οΈ Other (Bug fix, refactoring, docs) ## Visual Preview N/A (internal refactoring only) ## Checklist before requesting a review: - [x] I have read the `CONTRIBUTING.md` file. - [x] I have tested these changes locally (`localhost:3000/api/streak?user=YOUR_USERNAME`). - [x] I have run `npm run format` and `npm run lint` locally and resolved all errors (CI will fail otherwise). - [x] My commits follow the Conventional Commits format (e.g., `feat(themes): ...`, `fix(calculate): ...`). - [ ] I have updated `README.md` if I added a new theme or URL parameter. - [x] I have started the repo. - [x] I have made sure that i have only one commit to merge in this PR. - [ ] The SVG output matches the CommitPulse "premium quality" aesthetic standard (no raw elements, smooth animations, correct fonts). - [x] (Recommended) I joined the CommitPulse Discord community for contributor discussions, mentorship, and faster PR support.
2 parents 78e32cd + 3463d93 commit 5363800

2 files changed

Lines changed: 26 additions & 16 deletions

File tree

β€Žhooks/useRecentSearches.test.tsβ€Ž

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { describe, it, expect, beforeEach } from 'vitest';
22
import { renderHook, act } from '@testing-library/react';
3-
import { useRecentSearches } from './useRecentSearches';
3+
import { useRecentSearches, MAX_SEARCHES } from './useRecentSearches';
44

55
const store: Record<string, string> = {};
66

@@ -49,14 +49,17 @@ describe('useRecentSearches', () => {
4949
expect(result.current.searches.length).toBe(2);
5050
});
5151

52-
it('caps at 5 entries', () => {
52+
it(`caps at ${MAX_SEARCHES} entries`, () => {
5353
const { result } = renderHook(() => useRecentSearches());
54-
['a', 'b', 'c', 'd', 'e', 'f'].forEach((u) => {
54+
const testData = Array.from({ length: MAX_SEARCHES + 1 }, (_, i) =>
55+
String.fromCharCode(97 + i)
56+
);
57+
testData.forEach((u) => {
5558
act(() => {
5659
result.current.addSearch(u);
5760
});
5861
});
59-
expect(result.current.searches.length).toBe(5);
62+
expect(result.current.searches.length).toBe(MAX_SEARCHES);
6063
});
6164

6265
it('clears all searches', () => {

β€Žhooks/useRecentSearches.tsβ€Ž

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,15 @@
22

33
import { useState, useEffect } from 'react';
44

5-
const KEY = 'recentSearches';
6-
const MAX = 5;
5+
export const STORAGE_KEY = 'recentSearches';
6+
export const MAX_SEARCHES = 5;
77

88
type State = { searches: string[]; mounted: boolean };
99

1010
function loadFromStorage(): string[] {
1111
let saved: string[] = [];
1212
try {
13-
const stored = localStorage.getItem(KEY);
13+
const stored = localStorage.getItem(STORAGE_KEY);
1414
if (stored) saved = JSON.parse(stored) as string[];
1515
} catch {
1616
// ignore malformed storage
@@ -21,11 +21,11 @@ function loadFromStorage(): string[] {
2121
function writeStorage(searches: string[] | null): void {
2222
try {
2323
if (searches === null) {
24-
localStorage.removeItem(KEY);
24+
localStorage.removeItem(STORAGE_KEY);
2525
return;
2626
}
2727

28-
localStorage.setItem(KEY, JSON.stringify(searches));
28+
localStorage.setItem(STORAGE_KEY, JSON.stringify(searches));
2929
} catch {
3030
// ignore storage write failures
3131
}
@@ -40,8 +40,13 @@ export function useRecentSearches() {
4040
const [state, setState] = useState<State>({ searches: [], mounted: false });
4141

4242
useEffect(() => {
43-
const saved = loadFromStorage();
44-
43+
let saved: string[] = [];
44+
try {
45+
const stored = localStorage.getItem(STORAGE_KEY);
46+
if (stored) saved = JSON.parse(stored) as string[];
47+
} catch {
48+
// ignore malformed storage
49+
}
4550
// Single setState call β€” reads external system (localStorage) and syncs
4651
// React state in one update, which is exactly what effects are for.
4752
// eslint-disable-next-line react-hooks/set-state-in-effect
@@ -51,17 +56,19 @@ export function useRecentSearches() {
5156
const addSearch = (query: string) => {
5257
if (!query.trim()) return;
5358
setState((prev) => {
54-
const deduped = [query, ...prev.searches.filter((s) => s !== query)].slice(0, MAX);
55-
56-
writeStorage(deduped);
57-
59+
const deduped = [query, ...prev.searches.filter((s) => s !== query)].slice(0, MAX_SEARCHES);
60+
try {
61+
localStorage.setItem(STORAGE_KEY, JSON.stringify(deduped));
62+
} catch {}
5863
return { ...prev, searches: deduped };
5964
});
6065
};
6166

6267
const clearSearches = () => {
6368
setState((prev) => ({ ...prev, searches: [] }));
64-
writeStorage(null);
69+
try {
70+
localStorage.removeItem(STORAGE_KEY);
71+
} catch {}
6572
};
6673

6774
// Return empty searches until after hydration to prevent SSR/client mismatch.

0 commit comments

Comments
Β (0)