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

@compozed/redux-delux

v0.2.0

Published

Manage RESTful API transactions without the boilerplate

Downloads

9

Readme

redux-delux

redux-delux eliminates the boilerplate typically required to manage RESTful API transactions within a React/Redux application. Using redux-delux, you get Redux-like access to the data recieved from your API (along with metadata like loading and error status), all without writing a single reducer or action creator.

Redux store setup

If you don't need to setup any of your own reducers, you can setup the redux store with rr.reducers.

   import rd from 'redux-delux';
   
   export default(initialState) => {
     return createStore(
       rr.reducers,
       initialState,
       applyMiddleware(...middleware)
     );
   }
   

If you want to setup your own reducers, you can use rr.combineReducers.

   import rd from 'redux-delux';
   
   export default(initialState) => {
     return createStore(
       rr.combineReducers({myData: myReducer}),
       initialState,
       applyMiddleware(...middleware)
     );
   }
   

API setup

The redux-delux API for a project is defined as an object with request and task keys.

    export default {
        request: {
          getItems,
          getItemsForUser
        },
        task: {
          createItem,
          deleteItem
        }
    };

Request

Requests are used get data from an API. Requests store the status (loading, error, response data) of the most recent call (in the requestStatus object in the store).

API requests can be defined either by a URL (string)

    import rd from 'redux-delux';
    
    export default rr.apiRequest('/items');

or by a function that returns a URL (string)

    import rd from 'redux-delux';
    
    const getItemsForUser = (userId) => {
        return `/items/user/${userId}`;
    };
    
    export default rr.apiRequest(getItems);

Task

Tasks are used to take an action (typically via an API). The status (loading, error, success) is saved for every task, but tasks do not automatically manage response data.

API tasks are defined by a function which returns an array of sub-tasks (functions). The example below will create a new item for a user, and then re-request the item list for that same user.

    import rd from 'redux-delux';
    import getItemsForUser from "../getItemsForUser";
    import axios from 'axios';
    
    export const createItem = (userId, itemId, itemName, dispatch) => {
        const url = `/items`;
        const subTask1 = () => axios.post(url, {id: itemId, name: itemName, userId});
        const subTask2 = () => getItemsForUser.request(userId)(dispatch);
        return [subTask1, subTask2];
    };
    
    export default rr.apiTask(createItem);

Each sub-task receives an array containing the results of all previous sub-tasks as an argument. This makes it possible to update existing data in the store with the response of this task (such as a POST's response).

    import rd from 'redux-delux';
    import getItems from "../getItems";
    import axios from 'axios';
    
    export const createItem = (itemName, dispatch) => {
        const url = `/apps`;
        const subTask1 = () => axios.post(url, {name: itemName});
        const subTask2 = (previousSubTaskResults) => getItems.patch(dispatch,
            (existingData)=> {
                const items = existingData;
                const newItem = previousSubTaskResults[0].data;
                const updatedItems = [...items, newItem];
                return updatedItems;
            }
        );        
        
        return [subTask1, subTask2];
    };
    
    export default rr.apiTask(createItem);

As of version 0.2.0, it is possible to pass an optional second argument to rr.apiTask in order to enable storing the reponse data. The second argument should be a function which takes an array and returns the data you want to store as associated with that task. The array contains the results of each sub-task.

redux-delux within React components

connect

The redux-delux api can be injected into React components using connect. As with react-redux, 'mapStateToProps' and 'mapDispatchToProps' are optional arguments.

    import rd from 'redux-delux';
    import api from './api'; // as defined above
    
    rr.connect(api, mapStateToProps, mapDispatchToProps)(Component)

usage

A connected component will be injected by react-redux with the following props (based on the API definition shown above).

    this.props = {
        request:{
            getItems,
            getItemsForUser
        },
        requestStatus: {
            getItems,
            getItemsForUser
        },
        task: {
            createItem,
            deleteItem
        },
        taskStatus: function taskStatus(taskId){}
    }
request

request object is used to make a network request for data.

    import rd from 'redux-delux';
    
    class App extends Component {
    
      componentDidMount(){
          this.props.request.getItemsForUser('userId-123')
      }
    
      render() {
          return (
              <p>My React App</p>
          );
      }
    }
    
    rr.connect(api)(App)
requestStatus

requestStatus object is used to get the results of a request network call.

    import rd from 'redux-delux';
    
    class App extends Component {
    
      componentDidMount(){
          this.props.request.getItemsForUser('userId-123')
      }
    
      render() {
      
          const userItems = this.props.requestStatus.getItemsForUser('userId-123');
      
          return (
            {
                userItems.isLoading &&
                <p>Loading user data..</p>
            }
            {
                userItems.data &&
                <p>User data loading complete</p>
            }      
            <p>My React App</p>
          );
      }
    }
    
    rr.connect(api)(App)
task

task object is used to execute a redux-delux task.

    import rd from 'redux-delux';
    
    class App extends Component {
    
      componentDidMount(){
          this.props.request.getItemsForUser('userId-123')
      }
    
      render() {
      
          const userItems = this.props.requestStatus.getItemsForUser('userId-123');
      
          return (
            {
                userItems.isLoading &&
                <p>Loading user data..</p>
            }
            {
                userItems.data &&
                <p>User data loading complete</p>
            }      
            <p>My React App</p>
            <button onClick={()=>{this.props.task.createItem('New Item Title')}}/>
          );
      }
    }
    
    rr.connect(api)(App)
taskStatus

taskStatus object is used to review the status of a task.

    import rd from 'redux-delux';
    
    class App extends Component {
    
      constructor(){
        super();
        this.state = {taskId: ''}
      }
    
      componentDidMount(){
          this.props.request.getItemsForUser('userId-123')
      }
      
      createItem = async () => {
        const id = await this.props.task.createItem('New Item Title');
        this.setState({taskId: id});
      }
    
      render() {
      
          const userItems = this.props.requestStatus.getItemsForUser('userId-123');
          const taskStatus = this.props.taskStatus(this.state.taskId);
      
          return (
            {
                userItems.isLoading &&
                <p>Loading user data..</p>
            }
            {
                userItems.data &&
                <p>User data loading complete</p>
            }      
            <p>My React App</p>
            <button onClick={this.createItem}/>
            {
                taskStatus.isLoading &&
                <p>Adding item...</p>
            }
            {
                taskStatus.success &&
                <p>Item Added</p>
            }
          );
      }
    }
    
    rr.connect(api)(App)
Using redux-delux outside of React components

Status can be used to get the results of a network call. You must first pass the root state into the status function, and then call it with the arguments that are specified when the api request was setup.

    // selectors.js

    export const selectorCoolItems = (state) => {
    
        const userId = state.uiState.userId;
        const itemsForUser = api.request.getItemsForUser.status(state)(userId);    
        
        // derive new data
        return itemsForUser.data.filter(item => (item.coolness > 10) );
    }

watch out

  • redux-delux uses _rr key in the root of the redux store
  • redux-delux uses request, requestStatus, task, and taskStatus in this.props for connected components
  • redux-delux uses redux actions with types starting with _rr