Skip to content

Draft: Entity store

Alex Gleason requested to merge entity-store into develop

Summary

This is an attempt to simplify the way we deal with fetching/pagination with more flexibility than React Query can offer.

In short, this is the API:

function useNotifications() {
  return useEntities<Notification>(['Notification', ''], '/api/v1/notifications');
}
const {
  entities: notifications,
  isLoading,
  isFetching,
  hasNextPage,
  fetchEntities,
  fetchNextPage,
} = useNotifications();

useEffect(() => {
  if (!isLoading) {
    fetchEntities();
  }
}, []);

return notifications.map(n => <Notification notification={n} />);

Meanwhile, the store looks like this:

/** A Mastodon API entity. */
interface Entity {
  /** Unique ID for the entity (usually the primary key in the database). */
  id: string
}

/** Cache data pertaining to a paritcular entity type.. */
interface EntityCache {
  /** Map of entities of this type. */
  store: {
    [id: string]: Entity | undefined
  }
  /** Lists of entity IDs for a particular purpose. */
  lists: {
    [listKey: string]: EntityList | undefined
  }
}

interface ReducerState {
  [entityType: string]: EntityCache | undefined
}

It revolves around the idea that entities have IDs, and saves them into a map. Then lists of IDs can be created for any purpose to pull entities out of the store.

Also, it can deal with websocket events better than React Query by simply dispatching a Redux action to mutate the cache.

TODO:

  • Actions
  • Reducer
  • Pagination
  • useEntities() hook
  • useEntity() hook
  • Normalizers
  • Sub-Entities
  • Max age
  • Clear cache
Edited by Alex Gleason

Merge request reports