Skip to content

Latest commit

 

History

History
71 lines (55 loc) · 2.52 KB

pagination.md

File metadata and controls

71 lines (55 loc) · 2.52 KB

Pagination

While this page focuses on the pagination structure provided by Daxus, you can also define your own pagination data structure.

createPaginationAdapter

Daxus provides the createPaginationAdapter function to help developers manage pagination data easily.

export type Id = string | number;

export interface PaginationMeta {
  ids: Id[];
  noMore: boolean;
}

export interface Pagination<Data> {
  items: Data[];
  noMore: boolean;
}

export interface PaginationState<Data> {
  // The key of this record is the id of each entity.
  entityRecord: Record<string, Data | undefined>;
  // The key of this record is generated by developers.
  paginationMetaRecord: Record<string, PaginationMeta | undefined>;
}

In this data structure, all data instances will be stored in the entityRecord. The pagination data will be generated from the PaginationMeta. If two paginations contain the same entity (i.e., the same id), they will reference the same entity instance. As a result, if the entity is updated, the two paginations will also be updated. Developers don't need to worry about data inconsistency.

createPaginationAdapter will return an object that contains the initial state and various operation functions. You can pass the initial state when you create a model and use the operation functions to read or write the model's state.

const postAdapter = createPaginationAdapter<Post>();
const postModel = createModel({ initialState: postAdapter.getInitialState() });

const getPost = postModel.defineAccessor<Post, string>({
  fetchData: postId => {
    return getPostApi(postId);
  },
  syncState: (draft, payload) => {
    postAdapter.upsertOne(draft, payload.data); // Update the entity in the entityRecord. If it doesn't exist, create one.
  },
});

function usePost(postId: string) {
  return useAccessor(getPost(postId), state => postAdapter.tryReadOne(state, postId));
}

Normal or Infinite Accessor

If the API is cursor-based, you may need to define an infinite accessor:

const getPostList = postModel.defineInfiniteAccessor<
  { items: Post[]; nextKey: string | null },
  string
>({
  fetchData: (filter, { previousData }) => {
    if (previousData.nextKey === null) return null;
    return getPostListApi({ filter, nextKey: previousData?.nextKey });
  },
  syncState: (draft, payload) => {
    postAdapter.appendPagination(draft, `filter=${payload.arg}`, payload.data.items);
  },
});

In other cases, a normal accessor may be sufficient. However, you can also always use an infinite accessor for fetching lists.