DEV Community

Xuan
Xuan

Posted on • Edited on

Introducing Daxus - The Design Philosophy

The Design Philosophy Behind Daxus

This article is also included in https://github.com/jason89521/daxus#design-philosophy

Using Redux has its advantages, especially when it comes to customizing data structures. In our company, pagination is one of the most frequently used data structures for various entities like posts, comments, and forums. To simplify the process of creating paginations, our senior engineer developed a createPaginationAdapter function.

The state type returned by createPaginationAdapter is defined as follows:

export interface Pagination {
  noMore: boolean;
  index: EntityId[];
  loading: boolean;
  fetched: boolean;
  error?: any;
}

export interface PaginationState<T> {
  data: Record<EntityId, T | undefined>;
  paginations: Record<string, Pagination | undefined>;
}
Enter fullscreen mode Exit fullscreen mode

PaginationState consists of two properties: data and paginations. data stores all the entity data, while paginations keeps track of the pagination states and the associated IDs.

To illustrate, let's consider the example of managing posts. When retrieving the list of posts without any filters, the API endpoint would look like /api/posts?filter=all, and the corresponding pagination key would be filter=all. Suppose the API returns the first page of posts with IDs 1 to 5. In this case, paginations["filter=all"] would contain the following:

{
    noMore: false,
    index: [1, 2, 3, 4, 5],
    loading: false,
    fetched: true
}
Enter fullscreen mode Exit fullscreen mode

The data object would store the actual post data:

{
    1: {
        // post data
    },
    // and so on
}
Enter fullscreen mode Exit fullscreen mode

To access the pagination for filter=all, we can use the object obtained from createPaginationAdapter:

const postAdapter = createPaginationAdapter();

function usePost() {
  const postPagination = useSelector(state =>
    postAdapter.selectByPagination(state.post, 'filter=all')
  );
  return postPagination;
}
Enter fullscreen mode Exit fullscreen mode

At this point, you might think, "Isn't this similar to RTK's createEntityAdapter?" Indeed, there are similarities between the two, but createPaginationAdapter is an enhanced version specifically designed for pagination data. Now, let's delve into its most significant advantage.

Do you remember when React Query fails to meet our needs? Yes, it's when we have multiple paginations that might include the same post. React Query cannot handle this scenario effectively, but the pagination adapter perfectly solves this problem. By centralizing all the data in data and using paginations to collect the associated IDs, any updates to a specific post will automatically reflect in all the paginations containing that post. There won't be any inconsistencies.

So, what is the design philosophy behind Daxus?

The answer lies in customized data structures.

Every application has unique requirements for data structures. In our company, we designed PaginationState to fulfill our needs. Daxus's design philosophy empowers developers to define and use data structures tailored to their specific requirements. You only need to invest effort in creating suitable adapters and instructing Daxus on how to fetch data and synchronize it with your model. Daxus takes care of the rest, including deduplication, revalidation, and more.

However, creating an adapter does require some code, so Daxus also strives to provide pre-built adapters that cater to most use cases. If you have any new data structures in mind that Daxus doesn't support yet, we welcome your suggestions, and we'll make an effort to implement them.

Currently, Daxus only offers createPaginationAdapter, and I haven't thought of other forms of data structures. If you have any ideas, please let me know!

You can give Daxus a try and provide me with any feedback. Thank you!

The repo of Daxus: https://github.com/jason89521/react-server-model

Top comments (0)