From a19b1e83a9a7e9ee426813cbcb8f11e4c3d892d0 Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Mon, 13 Mar 2023 16:39:23 -0500 Subject: [PATCH] EntityStore: parse entities after fetch, not during render (performance) --- app/soapbox/entity-store/hooks/useEntities.ts | 12 +++++++----- app/soapbox/entity-store/hooks/useEntity.ts | 9 +++------ 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/app/soapbox/entity-store/hooks/useEntities.ts b/app/soapbox/entity-store/hooks/useEntities.ts index fa7e26d626..72cec62f52 100644 --- a/app/soapbox/entity-store/hooks/useEntities.ts +++ b/app/soapbox/entity-store/hooks/useEntities.ts @@ -3,6 +3,7 @@ import z from 'zod'; import { getNextLink, getPrevLink } from 'soapbox/api'; import { useApi, useAppDispatch, useAppSelector } from 'soapbox/hooks'; +import { filteredArray } from 'soapbox/schemas/utils'; import { entitiesFetchFail, entitiesFetchRequest, entitiesFetchSuccess } from '../actions'; @@ -52,10 +53,9 @@ function useEntities( const entities: readonly TEntity[] = entityIds ? ( Array.from(entityIds).reduce((result, id) => { - // TODO: parse after fetch, not during render. - const entity = schema.safeParse(cache?.store[id]); - if (entity.success) { - result.push(entity.data); + const entity = cache?.store[id]; + if (entity) { + result.push(entity as TEntity); } return result; }, []) @@ -74,7 +74,9 @@ function useEntities( dispatch(entitiesFetchRequest(entityType, listKey)); try { const response = await api.get(url); - dispatch(entitiesFetchSuccess(response.data, entityType, listKey, { + const entities = filteredArray(schema).parse(response.data); + + dispatch(entitiesFetchSuccess(entities, entityType, listKey, { next: getNextLink(response), prev: getPrevLink(response), fetching: false, diff --git a/app/soapbox/entity-store/hooks/useEntity.ts b/app/soapbox/entity-store/hooks/useEntity.ts index d242c9b4ef..92f20560ec 100644 --- a/app/soapbox/entity-store/hooks/useEntity.ts +++ b/app/soapbox/entity-store/hooks/useEntity.ts @@ -30,11 +30,7 @@ function useEntity( const defaultSchema = z.custom(); const schema = opts.schema || defaultSchema; - const entity = useAppSelector(state => { - // TODO: parse after fetch, not during render. - const result = schema.safeParse(state.entities[entityType]?.store[entityId]); - return result.success ? result.data : undefined; - }); + const entity = useAppSelector(state => state.entities[entityType]?.store[entityId] as TEntity | undefined); const [isFetching, setIsFetching] = useState(false); const isLoading = isFetching && !entity; @@ -42,7 +38,8 @@ function useEntity( const fetchEntity = () => { setIsFetching(true); api.get(endpoint).then(({ data }) => { - dispatch(importEntities([data], entityType)); + const entity = schema.parse(data); + dispatch(importEntities([entity], entityType)); setIsFetching(false); }).catch(() => { setIsFetching(false);