Redux state with paginated relational data

How would you approach the Redux state shape and/or reducers composition for paginated and relationnal data, such as paginated posts from a specific category fetched from a WordPress API (eg.: …/posts?categories=11) ?

I’m currently dealing it this way:

const reducer = (state = {}, action) => {
  switch (action.type) {
    case 'RECEIVE_POSTS': {
      const { data } = action.payload.result // normalized data
      return { ...state, [action.meta.page || '1']: data }
    }
    default: return state
  }
}

const list = (listName, predicate, getSublistName) => (state, action) => {
  if (action.error || listName != predicate(action)) {
    return state
  } else if (getSublistName) {
    const sublistName = getSublistName(action)
    return { ...state, [sublistName]: reducer(state[sublistName], action) }
  }
  return reducer(state, action)
}

export const reducer = combineReducers({
  categories: list(
    'categories',
    (action) => action.meta && action.meta.list,
    (action) => action.meta && head(action.meta.categories)) // head comes from Lodash
  ),
  search: list(
    'search', 
    (action) => action.meta && action.meta.list
  ),
  ...
}

It works, but I feel that either the list higher order reducer could be improved by being agnostic in regard to a deeper nesting (which feels wrong…), or the resulting state shape is nested too much.

I can’t wrap my head to get a totally flat state, except by using entries like a postsCategories array of posts objects with a post/category and page number, but then data would be duplicated a lot (which feels also wrong…).

There are some libraries for pagination but I don’t believe any of them handle this.

Is it about reducer composition or state shape? Both?

Read more here: Redux state with paginated relational data

Leave a Reply

Your email address will not be published. Required fields are marked *