-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.js
58 lines (52 loc) · 1.75 KB
/
index.js
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
import { useEffect, useReducer, useState } from "react";
import { useDebounce } from "use-debounce";
const capitalize = (str) => {
return str.charAt(0).toUpperCase() + str.slice(1);
};
export const search = ({ index, term, excerpt, limit = 25 }) => {
let searchUrl = `/.netlify/functions/search${capitalize(index)}?term=${term}`;
if (limit) searchUrl = `${searchUrl}&limit=${limit}`;
if (excerpt) searchUrl = `${searchUrl}&excerpt=${excerpt}`;
return fetch(searchUrl).then((response) => response.json());
};
const reducer = (state, action) => {
switch (action.type) {
case "startSearch":
return { loading: true, error: state.error, results: state.results };
case "endSearch":
return { loading: false, error: action.error, results: action.results };
default:
throw new Error();
}
};
export const useSearch = (
index,
{ defaultSearchTerm = "", debounce = 250, limit = 25, excerpt = false } = {}
) => {
const [searchTerm, setSearchTerm] = useState(defaultSearchTerm);
const initialState = {
loading: Boolean(defaultSearchTerm && defaultSearchTerm !== ""),
error: null,
results: [],
};
const [{ loading, results, error }, dispatch] = useReducer(
reducer,
initialState
);
const [term] = useDebounce(searchTerm, debounce);
useEffect(() => {
if (term && term !== "") {
dispatch({ type: "startSearch" });
search({ index, term, limit, excerpt })
.then((response) =>
dispatch({
type: "endSearch",
results: response.results,
error: null,
})
)
.catch((error) => dispatch({ type: "endSearch", results: [], error }));
}
}, [index, term, limit, excerpt]);
return [searchTerm, setSearchTerm, results, loading, error];
};