cantierecreativo/redux-bees

Pagination

Opened this issue · 1 comments

Hi, looking to use this on a project. Just had a quick question about doing pagination with the query HoC. Would you have any examples of doing that? query wouldn't provide enough on its own to support displaying a component with paging correct? The props it would provide would just be for the requests it performed. I was thinking you would have some kind of UI state in your store that controls the current page, query and perform would hook into that to issue calls and I guess I'd need a custom piece in my mapStateToProps to pull in all the data (existing calls that happened + the new page)?

Or would it be better to not use the HoC in those contexts? Just dispatch the events myself? Wondering how you guys handle pagination in your app that uses this library. Any guidance would be appreciated!

I realize this is an older issue and you've probably already moved on or found your own way to resolve it, but I wanted to at least answer with a solution that has worked for me regarding paging/sorting/filtering for the benefit of anyone else who comes along.

HoCs are useful, but as you notice in this case, it can be difficult to mix it with component state because then you need to elevate the state to a component that sits on top of the HoC in the render chain. If the HoC is composed from a lot of states (like paging/sorting/filtering) then you end up moving a ton of logic into that top-level component.

An alternative approach is to convert the HoC into a render prop component or "Provider" which gives you access to the same props as the HoC would give you, but without having to refactor all of your setState logic. This approach becomes even more formidable when you have two or more HoCs that need to interact with each other.

Take this hypothetical situation, a ManageBlogs component that renders data from an api.getBlogs endpoint:

import { query } from 'redux-bees'
import api from './api'
import Grid from './Grid'

const ManageBlogs = props => (
  <Grid data={props.blogs} loading={props.status.blogs.isLoading} />
)

const Enhanced = query('blogs', api.getBlogs)(ManageBlogs)

We can rewrite the query HoC to become a QueryProvider:

// a basic render prop component is a component that calls its "children" prop as a function.
const toRenderProp = ({children, ...rest}) => children(rest)

// A HoC that generates a render prop component to query the configured endpoint
const createQueryProvider = (...args) => query(...args)(toRenderProp)

// Put it together with our `api.getBlogs` endpoint to complete the Provider component
const BlogsProvider = createQueryProvider('blogs', api.getBlogs)

Then we can apply it to ManageBlogs as part of the render:

class ManageBlogs extends React.Component {
  state = { page: 1, per: 10 }

  handlePageChange = ({page, per}) => this.setState({ page, per })

  render() {
    return (
      <BlogsProvider params={this.state}>
        {({blogs, status}) => (
          <Grid data={blogs} loading={status.blogs.isLoading} onPageChange={this.handlePageChange} />
        )}
      </BlogsProvider>
    )
  }
}

As a bonus, you can decorate virtually any HoC as a Provider using the same technique!