npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

paging-dr-redux

v1.0.1

Published

A bare-bones paginator which works well with redux

Downloads

5

Readme

paging-dr-redux

Paging Dr. Redux!, a bare-bones paginator designed to work with Redux.

Dependencies

This is intended to be used with Redux, typically within the context of a React application, using redux-thunk; best results will come if this is your setup.

This also uses Flux Standard Actions for consistency's sake; not a dependency, but it's a tool which you can use along with this lib.

Installation

Using npm:

$ npm i --save paging-dr-redux

Quick Start

First, we'll need to set up a function which calls the API and returns a promise. How you decide to implement that is up to you; We'll use fetch for this example.

// api.js

import queryStringUtil from 'query-string'

export const getTodos = (queryParamsObject = {}) => {
    const url = "http://example.com?" + queryStringUtil.stringify(queryParamsObject);
    return fetch(url)
        .then(
            response => response.json(),
            error => console.log(error)
        );
}

Now we'll create the paginator object we're going to use. For now, we'll use the default options for building the paginator.

// paginators.js

import getPaginator from 'paging-dr-redux';
import {getTodos} from './api';

export const todoPaginator = getPaginator('todo', getTodos); 

The paginator provides reducers, so we'll get those into our application

// reducers.js

import {todoPaginator} from './paginators';
import {combineReducers} from 'redux';

const todoReducer = combineReducers({
    entities: todoPaginator.entitiesReducer,
    pagination: todoPaginator.paginationReducer
});

// maybe have other reducers here

const reducers = combineReducers({
    todos: todoReducer
});
export default reducers;

Build your store and app as you normally would, and now you have a paginator ready for your components! Here's a (pretty thorough) example of what you can do

// components/App.js

import React, { Component } from 'react';
import {connect} from 'react-redux';
import {todoPaginator} from "../paginators";

class App extends Component {
    constructor(props) {
        super(props);

        this.onNextClick = this.onNextClick.bind(this);
        this.onPreviousClick = this.onPreviousClick.bind(this);
        this.onFilterChange = this.onFilterChange.bind(this);
    }

    componentWillMount() {
        this.props.dispatch(this.props.fetchPage());
    }

    onNextClick() {
        if (!this.props.hasNext) {
            return;
        }
        this.props.dispatch(this.props.fetchNextPage());
    }

    onPreviousClick() {
        if (!this.props.hasPrevious) {
            return;
        }
        this.props.dispatch(this.props.fetchPreviousPage());
    }

    onFilterChange(evt) {
        this.props.dispatch(this.props.fetchPage(1, {category_id: evt.target.value}));
    }

    render() {
        const {
            hasPrevious,
            hasNext,
            currentPageItems,
            totalCount,
            filtersAsQueryString,
            currentPageNum,
        } = this.props;
        return (
            <div>
                <h1>Total of {totalCount} todo items</h1>
                <h2>There are {Object.keys(currentPageItems).length} in this list</h2>
                <h2>Filter: {filtersAsQueryString}</h2>
                <h2>On page {currentPageNum}</h2>

                <button onClick={this.onPreviousClick} disabled={!hasPrevious}>Previous</button>
                <button onClick={this.onNextClick} disabled={!hasNext}>Next</button>
                <select onChange={this.onFilterChange}>
                    {Array(8).fill().map((_, i) => <option value={i + 1} key={'s' + i}>{i + 1}</option>)}
                </select>
                <table>
                    <thead>
                        <tr>
                            <th>id</th>
                            <th>body</th>
                            <th>category</th>
                        </tr>
                    </thead>
                    <tbody>
                    {
                        currentPageItems.map(todo => (
                            <tr key={todo.id}>
                                <td>{todo.id}</td>
                                <td>{todo.body}</td>
                                <td>{todo.category_id}</td>
                            </tr>
                        ))
                    }
                    </tbody>
                </table>
            </div>
        )
    }
}

const mapStateToProps = state => {
    return {
        hasPrevious: partsPaginator.selectors.hasPrevious(state.todos),
        hasNext: partsPaginator.selectors.hasNext(state.todos),
        currentPageItems: partsPaginator.selectors.getCurrentPageItems(state.todos),
        totalCount: partsPaginator.selectors.getTotalCount(state.todos),
        filtersAsQueryString: partsPaginator.selectors.getFiltersAsQueryString(state.todos),
        currentPageNum: partsPaginator.selectors.getCurrentPageNum(state.todos),
        filters: partsPaginator.selectors.getFilters(state.todos),
        fetchNextPage: partsPaginator.navigation.fetchNextPage(state.todos),
        fetchPreviousPage: partsPaginator.navigation.fetchPreviousPage(state.todos),
        fetchPage: partsPaginator.navigation.fetchPage(state.todos),
    }
};

export default connect(mapStateToProps)(App);

Revision History

1.0.0

Major version bump due to breaking changes in the API. This adds a specific type to the getPaginator function in order to differentiate between different entity types which may be paginated, preventing sullying of the entity space

0.1.4

Patch fix to repair an issue with nested promises

0.1.3

Use the lib dir, not the dist dir, as the target for compiled code

0.1.2

Updated README with instructions on how to use

0.1.1

Added transpile options, first upload to NPM

0.1.0

First working iteration