diff --git a/.jules/bolt.md b/.jules/bolt.md new file mode 100644 index 0000000..fa183ed --- /dev/null +++ b/.jules/bolt.md @@ -0,0 +1,3 @@ +## 2025-02-28 - [Concurrent Data Fetching] +**Learning:** Sequential data fetching can significantly increase page load latency. Combining independent fetch requests using `Promise.all` allows them to process concurrently, preventing network waterfalls. +**Action:** When implementing page components that require multiple independent data streams, analyze if they can be fetched in parallel using `Promise.all` rather than using sequential `await fetch()` calls. diff --git a/src/app/projects/[id]/page.tsx b/src/app/projects/[id]/page.tsx index 3e63eb8..2b08d39 100644 --- a/src/app/projects/[id]/page.tsx +++ b/src/app/projects/[id]/page.tsx @@ -49,50 +49,52 @@ export default function ProjectDetailPage({ params }: { params: Promise<{ id: st return; } - if (isSignedIn && projectId) { - fetchProjectAndLists(); - } - }, [isLoaded, isSignedIn, projectId, router]); - - const fetchProjectAndLists = async () => { - try { - setIsLoading(true); - - // Fetch project details - const projectResponse = await fetch(`/api/projects/${projectId}`); - const projectResult = await projectResponse.json(); - - if (!projectResult.success) { - setError(projectResult.error || "Project not found"); - return; - } + const fetchProjectAndLists = async () => { + try { + setIsLoading(true); + + // Fetch data concurrently to reduce page load latency + const [projectResponse, listsResponse, allListsResponse] = await Promise.all([ + fetch(`/api/projects/${projectId}`), + fetch(`/api/projects/${projectId}/lists`), + fetch("/api/lists") + ]); + + // Parse JSON concurrently + const [projectResult, listsResult, allListsResult] = await Promise.all([ + projectResponse.json(), + listsResponse.json(), + allListsResponse.json() + ]); + + if (!projectResult.success) { + setError(projectResult.error || "Project not found"); + return; + } - setProject(projectResult.data); - setEditName(projectResult.data.name); - setEditDescription(projectResult.data.description || ""); + setProject(projectResult.data); + setEditName(projectResult.data.name); + setEditDescription(projectResult.data.description || ""); - // Fetch lists in project - const listsResponse = await fetch(`/api/projects/${projectId}/lists`); - const listsResult = await listsResponse.json(); + if (listsResult.success) { + setLists(listsResult.data); + } - if (listsResult.success) { - setLists(listsResult.data); + if (allListsResult.success) { + setAllLists(allListsResult.data); + } + } catch (err) { + console.error("Error fetching project:", err); + setError("Failed to load project"); + } finally { + setIsLoading(false); } + }; - // Fetch all user lists (for adding to project) - const allListsResponse = await fetch("/api/lists"); - const allListsResult = await allListsResponse.json(); - - if (allListsResult.success) { - setAllLists(allListsResult.data); - } - } catch (err) { - console.error("Error fetching project:", err); - setError("Failed to load project"); - } finally { - setIsLoading(false); + if (isSignedIn && projectId) { + fetchProjectAndLists(); } - }; + }, [isLoaded, isSignedIn, projectId, router]); const handleUpdateProject = async () => { if (!editName.trim()) {