This repository has been archived by the owner on Sep 18, 2024. It is now read-only.
forked from HHS/simpler-grants-gov
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add suspense boundary around search page results (#101)
## Summary Fixes #59 ### Time to review: __30 mins__ ## Changes proposed This makes the search page static and adds a suspense boundary for the data being fetched by the server. The data comes from the API and is called from 3 components: * [`<SearchPaginationFetch />`](https://github.com/navapbc/simpler-grants-gov/pull/101/files#diff-9dbdda5096b97ad049cccea24c5a046581d26c151a6f94fcc32c05cb33ee9dee) * [`<SearchResultsHeaderFetch />`](https://github.com/navapbc/simpler-grants-gov/pull/101/files#diff-14a084f66c050414cc2bbd0875256511630438971022073301bbfe91c4aa8cd1) * [`<SearchResultsListFetch />`](https://github.com/navapbc/simpler-grants-gov/pull/101/files#diff-aabe6a7d19434a9b26199430bbcde5d31a0790aebc4cd844b922ac2fa1348dce) This also simplifies the state model by pushing state changes directly to the browser query params and rerendering the changed items. This makes things a lot simpler and thus a lot of state management code is removed and there results list is no longer wrapped in a form and passing form refs between components. This is the recommended approach by next: https://nextjs.org/learn/dashboard-app/adding-search-and-pagination There are several items that needed to be shared among the client components: the query, total results count, and total pages. These are wrapped in a `<QueryProvider />` that updates the state of these items. This was added so that if someone enters a query in the text box and the clicks a filter their query is not lost, so that the "N Opportunities" text doesn't need to be rerendered when paging or sorting, and so that the pager stays the same length when paging or sorting. The data is fetched a couple of times in a duplicative fashion, however this follows [NextJS best practice](https://nextjs.org/docs/app/building-your-application/rendering/composition-patterns#sharing-data-between-components) since the requests are cached. The pager has been updated to reload only when there is a change in the page length. Because of an issue with the way the pager renders, it is unavailable while data is being updated: <img width="1229" alt="image" src="https://github.com/navapbc/simpler-grants-gov/assets/512243/a097b0e2-f646-43b5-bc5a-664db02780a2"> This is because the Truss React component [switches between a link and a button as it renders](https://github.com/trussworks/react-uswds/blob/main/src/components/Pagination/Pagination.tsx#L42) and there isn't an option to supply query arguments, so if a user where to click it they would lose the query params. Overall this puts us on nice footing for the upcoming work using NextJS best practice.
- Loading branch information
Showing
56 changed files
with
1,173 additions
and
1,897 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
"use client"; | ||
import { createContext, useCallback, useMemo, useState } from "react"; | ||
import { useSearchParams } from "next/navigation"; | ||
|
||
interface QueryContextParams { | ||
queryTerm: string | null | undefined; | ||
updateQueryTerm: (term: string) => void; | ||
totalPages: string | null | undefined; | ||
updateTotalPages: (page: string) => void; | ||
totalResults: string; | ||
updateTotalResults: (total: string) => void; | ||
} | ||
|
||
export const QueryContext = createContext({} as QueryContextParams); | ||
|
||
export default function QueryProvider({ | ||
children, | ||
}: { | ||
children: React.ReactNode; | ||
}) { | ||
const searchParams = useSearchParams() || undefined; | ||
const defaultTerm = searchParams?.get("query"); | ||
const [queryTerm, setQueryTerm] = useState(defaultTerm); | ||
const [totalPages, setTotalPages] = useState("na"); | ||
const [totalResults, setTotalResults] = useState(""); | ||
|
||
const updateQueryTerm = useCallback((term: string) => { | ||
setQueryTerm(term); | ||
}, []); | ||
|
||
const updateTotalResults = useCallback((total: string) => { | ||
setTotalResults(total); | ||
}, []); | ||
|
||
const updateTotalPages = useCallback((page: string) => { | ||
setTotalPages(page); | ||
}, []); | ||
|
||
const contextValue = useMemo( | ||
() => ({ | ||
queryTerm, | ||
updateQueryTerm, | ||
totalPages, | ||
updateTotalPages, | ||
totalResults, | ||
updateTotalResults, | ||
}), | ||
[ | ||
queryTerm, | ||
updateQueryTerm, | ||
totalPages, | ||
updateTotalPages, | ||
totalResults, | ||
updateTotalResults, | ||
], | ||
); | ||
|
||
return ( | ||
<QueryContext.Provider value={contextValue}> | ||
{children} | ||
</QueryContext.Provider> | ||
); | ||
} |
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.