Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to structure pagination state in Redux [closed]

TL;DR: How do you store pagination state in a Redux store given a large, normalized state tree with lots of resources, and multiple views displaying different paginated results?

I'm wondering what is the best way to store pagination data in a Redux store. This article prescribes storing pagination info as its own subtree within the state tree. I agree with that method, but here's where I disagree: the article suggests keying the pagination subtree by the type of resource being paginated, but what if there are several views that display paginated data of the same resource using different parameters? If you follow the article's method, your state tree may end up looking like this

{
  pagination: 
     todos: 
       count: 1000,
       nextPageUrl: ...,
       result: [list of id's]
     users:
       count: 200,
       nextPageUrl: ...,
       result: [list of id's]
}

This doesn't seem to make sense to me if you have multiple ways to view the same resource. What if on one screen there are multiple tables displaying todos that were fetched using different parameters? For instance, one table displays todos that were fetched from /api/todos/?userId=1 and another displays todos from /api/todos/?userId=2.

Given the above problem, it seems that a solution for allowing more flexible pagination is to store pagination state on a per-component basis, rather than a per-entity basis. So your state could look something like this

{
  pagination:
    componentId:
       count: 1000,
       nextPageUrl: ...,
       result: [list of id's]
    anotherComponentId:
       count: 1000,
       nextPageUrl: ...,
       result: [list of id's]
}

Of course, storing pagination results like this loses context as to what is being paginated. But is that so much of a problem? How do you go about paginating a large state tree with potentially multiple paginated results of the same resource? Thanks!

like image 682
Mitch W. Avatar asked Jan 17 '18 01:01

Mitch W.


Video Answer


1 Answers

I think that redux-cached-pagination (Demo here) can help to cope with your problem. Normalized search results are stored in redux in a tree like that:

{
  standard_store: {
    pagination: {
      searchPhrase__: {//results for given search params
        lastUpdateTime: 1516177824890,//last update time helps to refresh data in background
        pages: {    //each page is stored. You can adjust history length
          '1': {
            isFetching: false,//each page has fetching status
            isRefreshing: false,
            isSuccess: true,
            isFailed: false,
            lastUpdateTime: 1516177824891,
            elements: [ //in 'elements' array only ids are stored. Results are normalized
              100000,
              100001,
                ...
            ]
          }
        },
        elementsCount: 800
      },
      searchPhrase_a_: { //results for "a" search phrase
        lastUpdateTime: 1516177844624,
        pages: {
          '1': {
            isFetching: false,
            isRefreshing: false,
            isSuccess: true,
            isFailed: false,
            lastUpdateTime: 1516177844624,
            elements: [
              100001,
              100016,
              100017,
              100031,
              100044,
              100046,
              100049,
              100055,
              100056,
              100058,
              100065,
              100076,
              100077,
              100084,
              100088
            ]
          }
        },
        elementsCount: 138
      }
    },
    entities: { //here are stored entities. Entities are not duplicated. 
      '100000': {
        examData: 'BVUGUN',
        examIndexAtAll: 0,
        id: 100000
      },
      '100001': {
        examData: 'ZR7ADV',
        examIndexAtAll: 1,
        id: 100001
      },
        ...
    },
    paginationParams: {},
    searchParams: {
      searchPhrase: 'al'
    },
    currentPage: {
      pageNumber: 1
    }
  }
}

This json is copied directly from redux. Additionally you get features like refreshing results in background, simple use of virtualized list, storing last visited page and many others. If you want to use it in multiple lists I suggest to use reselect.

like image 125
Andrzej Avatar answered Nov 15 '22 22:11

Andrzej