feat(catalog/swr): Added a nice stale-while-revalidate pattern for fetching data

This commit is contained in:
blam
2020-06-12 00:29:42 +02:00
parent 2face4e519
commit 1a581d4d26
3 changed files with 24 additions and 22 deletions
+2 -2
View File
@@ -30,12 +30,12 @@
"@material-ui/core": "^4.9.1",
"@material-ui/icons": "^4.9.1",
"@material-ui/lab": "4.0.0-alpha.45",
"node-cache": "^5.1.1",
"react": "^16.13.1",
"react-dom": "^16.13.1",
"react-router": "^5.2.0",
"react-router-dom": "^5.2.0",
"react-use": "^14.2.0"
"react-use": "^14.2.0",
"swr": "^0.2.2"
},
"devDependencies": {
"@backstage/cli": "^0.1.1-alpha.7",
-11
View File
@@ -19,14 +19,9 @@ import {
Location,
LOCATION_ANNOTATION,
} from '@backstage/catalog-model';
import Cache from 'node-cache';
import { CatalogApi, EntityCompoundName } from './types';
export class CatalogClient implements CatalogApi {
// TODO(blam): This cache is just temporary until we have GraphQL.
// And client side caching using things like React Apollo or Relay.
// There's a lot of loading states that cause flickering around the app which aren't needed.
private cache: Cache;
private apiOrigin: string;
private basePath: string;
@@ -39,7 +34,6 @@ export class CatalogClient implements CatalogApi {
}) {
this.apiOrigin = apiOrigin;
this.basePath = basePath;
this.cache = new Cache({ stdTTL: 10 });
}
private async getRequired(path: string): Promise<any> {
@@ -79,11 +73,6 @@ export class CatalogClient implements CatalogApi {
async getEntities(
filter?: Record<string, string | string[]>,
): Promise<Entity[]> {
const cachedValue = this.cache.get<Entity[]>(
`get:${JSON.stringify(filter)}`,
);
if (cachedValue) return cachedValue;
let path = `/entities`;
if (filter) {
const params = new URLSearchParams();
@@ -33,9 +33,8 @@ import Edit from '@material-ui/icons/Edit';
import GitHub from '@material-ui/icons/GitHub';
import Star from '@material-ui/icons/Star';
import StarOutline from '@material-ui/icons/StarBorder';
import React, { FC, useCallback, useState } from 'react';
import React, { FC, useCallback, useState, useEffect } from 'react';
import { Link as RouterLink } from 'react-router-dom';
import { useAsync } from 'react-use';
import { catalogApiRef } from '../..';
import { defaultFilter, entityFilters, filterGroups } from '../../data/filters';
import { findLocationForEntityMeta } from '../../data/utils';
@@ -45,6 +44,7 @@ import {
CatalogFilterItem,
} from '../CatalogFilter/CatalogFilter';
import { CatalogTable } from '../CatalogTable/CatalogTable';
import useStaleWhileRevalidate from 'swr';
const useStyles = makeStyles(theme => ({
contentWrapper: {
@@ -70,11 +70,24 @@ export const CatalogPage: FC<{}> = () => {
defaultFilter,
);
const { value, error, loading } = useAsync(async () => {
const filter = entityFilters[selectedFilter.id];
const all = await catalogApi.getEntities();
return all.filter(e => filter(e, { isStarred: isStarredEntity(e) }));
}, [selectedFilter.id, starredEntities.size]);
const { data: entities, error, revalidate } = useStaleWhileRevalidate(
['catalog', entityFilters[selectedFilter.id]],
async (_, filter) => {
return await catalogApi.getEntities();
},
{ compare: () => false },
);
const data =
entities?.filter(e =>
entityFilters[selectedFilter.id](e, { isStarred: isStarredEntity(e) }),
) ?? [];
const revalidator = starredEntities.size || {};
useEffect(() => {
revalidate();
}, [revalidate, revalidator]);
const onFilterSelected = useCallback(
selected => setSelectedFilter(selected),
@@ -195,8 +208,8 @@ export const CatalogPage: FC<{}> = () => {
</div>
<CatalogTable
titlePreamble={selectedFilter.label}
entities={value || []}
loading={loading}
entities={data || []}
loading={!data && !error}
error={error}
actions={actions}
/>