Skip to content

Commit 629e6a9

Browse files
committed
Add loading and error states to search results
Introduces loading and error handling to the document search flow in App.tsx. Refactors the search logic to use async/await, improves key assignment for list items, and enhances UI feedback for users during data fetches and failures.
1 parent b52225c commit 629e6a9

File tree

1 file changed

+44
-29
lines changed
  • turing-js-sdk/js-sdk-sample/src

1 file changed

+44
-29
lines changed

turing-js-sdk/js-sdk-sample/src/App.tsx

Lines changed: 44 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -3,50 +3,65 @@ import { useEffect, useState } from "react";
33
import { useSearchParams } from "react-router-dom";
44

55
function App() {
6-
const [totalDocuments, setTotalDocuments] = useState<number>(0);
6+
const [totalDocuments, setTotalDocuments] = useState(0);
77
const [searchDocuments, setSearchDocuments] = useState<TurSNSiteSearchDocument[]>([]);
8+
const [loading, setLoading] = useState(false);
9+
const [error, setError] = useState<string | null>(null);
810
const [searchParams] = useSearchParams();
9-
const query = searchParams.get('q') || '*';
11+
const query = searchParams.get("q") || "*";
12+
1013
useEffect(() => {
11-
const searchService = new TurSNSiteSearchService(import.meta.env.VITE_API_URL);
12-
try {
13-
searchService.search(import.meta.env.VITE_SN_SITE, {
14-
q: query,
15-
rows: 10,
16-
currentPage: 1,
17-
localeRequest: import.meta.env.VITE_LOCALE,
18-
}).then(res => {
14+
const fetchDocuments = async () => {
15+
setLoading(true);
16+
setError(null);
17+
try {
18+
const searchService = new TurSNSiteSearchService(import.meta.env.VITE_API_URL);
19+
const res = await searchService.search(import.meta.env.VITE_SN_SITE, {
20+
q: query,
21+
rows: 10,
22+
currentPage: 1,
23+
localeRequest: import.meta.env.VITE_LOCALE,
24+
});
1925
setSearchDocuments(res.results?.document || []);
2026
setTotalDocuments(res.queryContext?.count || 0);
21-
});
22-
} catch (error: Error | any) {
23-
console.error('Search failed:', error.message);
24-
}
25-
}, [])
27+
} catch (err: any) {
28+
setError("Search failed: " + (err?.message || "Unknown error"));
29+
} finally {
30+
setLoading(false);
31+
}
32+
};
33+
fetchDocuments();
34+
}, [query]);
2635

2736
return (
2837
<div className="flex min-h-svh flex-col items-center justify-center">
29-
<div className="mb-4 text-lg font-semibold">Total Documents: {totalDocuments}</div>
38+
<div className="mb-4 text-lg font-semibold">
39+
Total Documents: {totalDocuments}
40+
</div>
41+
{loading && <div className="mb-4 text-gray-500">Loading...</div>}
42+
{error && <div className="mb-4 text-red-500">{error}</div>}
3043
<ul className="w-full max-w-md divide-y divide-gray-200 rounded-md border border-gray-300 bg-white shadow">
31-
{searchDocuments && searchDocuments.map((doc, index) => (
32-
<li key={index} className="p-4">
44+
{searchDocuments.map((doc, index) => (
45+
<li key={doc.fields?.url || index} className="p-4">
3346
<h3
3447
className="text-base font-medium"
35-
dangerouslySetInnerHTML={{ __html: doc.fields?.title }}
48+
dangerouslySetInnerHTML={{ __html: doc.fields?.title || "" }}
3649
/>
37-
38-
<a
39-
href={doc.fields?.url}
40-
target="_blank"
41-
rel="noopener noreferrer"
42-
>
43-
{doc.fields?.url}
44-
</a>
50+
{doc.fields?.url && (
51+
<a
52+
href={doc.fields.url}
53+
target="_blank"
54+
rel="noopener noreferrer"
55+
className="text-blue-600 underline break-all"
56+
>
57+
{doc.fields.url}
58+
</a>
59+
)}
4560
</li>
4661
))}
4762
</ul>
4863
</div>
49-
)
64+
);
5065
}
5166

52-
export default App
67+
export default App;

0 commit comments

Comments
 (0)