Repository navigation
Expand file tree
/
Copy pathSearch.tsx
More file actions
63 lines (55 loc) · 1.94 KB
/
Copy pathSearch.tsx
File metadata and controls
63 lines (55 loc) · 1.94 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
import type { FC } from 'react';
import type { SimplePost } from '../utils/posts.ts';
import { useCallback, useMemo, useState } from 'react';
import { PostHint } from './post/PostHint.tsx';
import Fuse from 'fuse.js';
export interface SearchProps {
posts: SimplePost[];
}
const loadSearchFromQueryParams = () => {
const { search } = window.location;
const params = new URLSearchParams(search);
return params.get('q') ?? '';
};
const updateSearchInQueryParams = (newSearchValue: string) => {
const params = new URLSearchParams();
params.set('q', newSearchValue);
window.history.replaceState(null, '', `?${params.toString()}`);
};
export const Search: FC<SearchProps> = ({ posts }) => {
const [searchValue, setSearchValue] = useState<string>(loadSearchFromQueryParams);
const updateSearch = useCallback((newSearchValue: string) => {
setSearchValue(newSearchValue);
updateSearchInQueryParams(newSearchValue);
}, []);
const fuse = useMemo(() => new Fuse(posts, { keys: ['body', 'title'],
}), [posts])
const results = useMemo(() => fuse.search(searchValue), [fuse, searchValue]);
return (
<>
<section className="mb-6">
<input
className="w-full border-2 focus:border-primary rounded p-2 outline-0 transition"
type="search"
name="q"
placeholder="Search…"
aria-label="Search"
autoComplete="off"
value={searchValue}
onChange={(e) => updateSearch(e.target.value)}
/>
</section>
<section>
{results.length === 0 && (
<>
{searchValue === '' && <p className="text-center">Enter a search term in the field above</p>}
{searchValue !== '' && <p className="text-center">No results found</p>}
</>
)}
{results.map(({ item: post }, index) => (
<PostHint key={index} url={post.url} title={post.title} excerpt={post.excerpt} />
))}
</section>
</>
);
}