Skip to content

Commit

Permalink
✨ store data catalog cache in useState
Browse files Browse the repository at this point in the history
  • Loading branch information
ikesau committed Sep 10, 2024
1 parent d412386 commit f571a36
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 28 deletions.
33 changes: 22 additions & 11 deletions site/DataCatalog/DataCatalog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@ import {
DataCatalogRibbonResult,
DataCatalogSearchResult,
getCountryData,
queryRibbonsWithCache,
querySearchWithCache,
queryRibbons,
querySearch,
syncDataCatalogURL,
} from "./DataCatalogUtils.js"
import {
Expand Down Expand Up @@ -818,8 +818,7 @@ export const DataCatalog = ({
const [state, dispatch] = useReducer(dataCatalogReducer, initialState)
const actions = createActions(dispatch)
const [isLoading, setIsLoading] = useState(false)
// Using useRef because updating isLoading already triggers a re-render
const cache = useRef<DataCatalogCache>({
const [cache, setCache] = useState<DataCatalogCache>({
ribbons: new Map(),
search: new Map(),
})
Expand All @@ -838,25 +837,37 @@ export const DataCatalog = ({

const stateAsUrl = dataCatalogStateToUrl(state)
const cacheKey = shouldShowRibbons ? "ribbons" : "search"
const currentResults = cache.current[cacheKey].get(stateAsUrl)
const currentResults = cache[cacheKey].get(stateAsUrl)

useEffect(() => {
async function fetchData() {
return shouldShowRibbons
? // TODO: what happens when 2 requests race?
queryRibbonsWithCache(searchClient, state, tagGraph, cache)
: querySearchWithCache(searchClient, state, cache)
const results = shouldShowRibbons
? await queryRibbons(searchClient, state, tagGraph)
: await querySearch(searchClient, state)
setCache((cache) => ({
...cache,
[cacheKey]: cache[cacheKey].set(stateAsUrl, results as any),
}))
}

syncDataCatalogURL(stateAsUrl)
analytics.logDataCatalogSearch(state)
if (cache.current[cacheKey].has(stateAsUrl)) return
if (cache[cacheKey].has(stateAsUrl)) return

setIsLoading(true)
fetchData()
.catch(Bugsnag.notify)
.finally(() => setIsLoading(false))
}, [state, searchClient, shouldShowRibbons, tagGraph, stateAsUrl, cacheKey])
return () => setIsLoading(false)
}, [
state,
searchClient,
shouldShowRibbons,
tagGraph,
stateAsUrl,
cacheKey,
cache,
])

useEffect(() => {
const handlePopState = () => {
Expand Down
24 changes: 7 additions & 17 deletions site/DataCatalog/DataCatalogUtils.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
import {
HitAttributeHighlightResult,
HitAttributeSnippetResult,
HitHighlightResult,
SearchForFacetValuesResponse,
SearchResponse,
} from "instantsearch.js"
import { getIndexName } from "../search/searchClient.js"
import { SearchIndexName } from "../search/searchTypes.js"
import { TagGraphRoot } from "@ourworldindata/types"
import { DataCatalogState, dataCatalogStateToUrl } from "./DataCatalogState.js"
import { DataCatalogState } from "./DataCatalogState.js"
import { countriesByName, Region } from "@ourworldindata/utils"
import { SearchClient } from "algoliasearch"

Expand Down Expand Up @@ -216,12 +214,11 @@ export function formatAlgoliaSearchResponse(
/**
* Async
*/
export async function queryRibbonsWithCache(
export async function queryRibbons(
searchClient: SearchClient,
state: DataCatalogState,
tagGraph: TagGraphRoot,
cache: React.MutableRefObject<DataCatalogCache>
): Promise<void> {
tagGraph: TagGraphRoot
): Promise<DataCatalogRibbonResult[]> {
const topicsForRibbons = getTopicsForRibbons(state.topics, tagGraph)
const searchParams = dataCatalogStateToAlgoliaQueries(
state,
Expand All @@ -232,21 +229,14 @@ export async function queryRibbonsWithCache(
.then((response) =>
formatAlgoliaRibbonsResponse(response, topicsForRibbons)
)
.then((formatted) => {
cache.current.ribbons.set(dataCatalogStateToUrl(state), formatted)
})
}

export async function querySearchWithCache(
export async function querySearch(
searchClient: SearchClient,
state: DataCatalogState,
cache: React.MutableRefObject<DataCatalogCache>
): Promise<void> {
state: DataCatalogState
): Promise<DataCatalogSearchResult> {
const searchParams = dataCatalogStateToAlgoliaQuery(state)
return searchClient
.search<IDataCatalogHit>(searchParams)
.then(formatAlgoliaSearchResponse)
.then((formatted) => {
cache.current.search.set(dataCatalogStateToUrl(state), formatted)
})
}

0 comments on commit f571a36

Please sign in to comment.