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

redux-rad-requests

v2.0.0

Published

Redux tooling for managing async request actions with react hooks. Prevent race conditions. Build responsive UIs. Rad.

Downloads

20

Readme

redux-rad-requests

It's kinda crazy that we've been building react/redux apps with an async requests model that allows race conditions by default.

redux-rad-requests is small set of tools that give you a powerful and concise way to manage and respond to your React app's various requests and their state.

It relies on a couple very good ideas: Redux, React Hooks, Promises, and Selectors.

This project has 100% test coverage.

Yes it works with react-native.

Why use it

  • Use it to turn any async action into a named request
  • Use it to prevent race conditions by dropping duplicate requests
  • Use it to build nice UI logic around request status
  • Use it to easily cancel and retry requests
  • Use it to keep all state in Redux where it belongs
  • Use it because you love React hooks and functional components

Why skip it

  • Skip it if you're not using Redux and react-redux
  • Skip it if you're not ready to use React hooks

How it Looks

import { useRequest } from 'redux-rad-request';

// Any React component that supports hooks
export default function MyApp () {
  const {
    start: handleButtonPress,
    isPending,
  } = useRequest(fetchSomething); // <-- HERE is the main hook

  const content = isPending
    ? <p>Loading something...</p>
    : <p>Your data is ready.</p>

  // mash this button all you want and never create a race condition
  return (
    <div>
      <button onPress={handleButtonPress}>Fetch Something</button>
      {content}
    </div>
  );
}

// A mostly normal Redux action creator
function fetchSomething () {
  return {
    type: 'FETCH_SOMETHING',
    meta: {
      requestId: 'FETCH_SOMETHING' // <-- HERE is where you name the request
    },
    async payload () {
      await pullOutAllTheStops();
      await battenDownTheHatches();
    }
  };
}

Make it Go

Install the npm package:

npm install --save redux-rad-requests

Or for you knitters out there:

yarn add redux-rad-requests

You're going to need to do a tiny bit of manual integration. There's both a reducer and a middleware component that needs to be installed. It should all look something like this:

// redux-store.js

import { applyMiddleware, combineReducers, createStore } from 'redux';

import {
  middleware as requestsMiddleware,
  reducer as requestsReducer
} from 'redux-rad-requests';

const reducers = combineReducers({
  // ...
  // your other reducers
  // ...
  requests: requestsReducer // <-- rad!
  // ...
  // your other reducers
  // ...
});

const middleware = applyMiddleware(
  // ...
  // your other redux middleware
  // ...
  requestsMiddleware() // <-- rad!
  // ...
  // your other redux middleware
  // ...
);

const store = createStore(reducers, middleware);

export default store;

Usage

Here's the API real quick. See the tests for details.

import { useRequest, useRequestStatus } from 'redux-rad-requests';

// in your React functional components...

const {
  start, // a function that dispatches the request action
  cancel, // a function that cancels the current named request
  retry, // a function that retries a failed request
  deferred, // a reference directly to the interal promise object
  requestId, // the request id as found after dispatching the action
  isPending, // true if the named request is pending
  isResolved, // true if the named request has been resolved
  isRejected, // true if the named request failed
  isCanceled  // true if the name request was canceled
} = useRequest(function myActionCreator () {
  return {
    type: 'MY_ACTION',
    meta: {
      // this action property must exist to make it a valid request
      // request id is usually the same as the action type,
      // but can be different if needed.
      requestId: 'MY_ACTION'
    }
    // this action property must exist to make it a valid request
    async payload () {
      // do your work here
    }
  }
}) 

// meanwhile in some other component ...

const {
  isPending, // true if the named request is pending
  isResolved, // true if the named request has been resolved
  isRejected, // true if the named request failed
  isCanceled  // true if the name request was canceled
} = useRequestStatus('MY_ACTION')

useRequestDispatcher is also a thing, but that's varsity level.

Get Thunky

While not required, redux-rad-requests plays very nicely with redux-thunk and redux-promise-middleware. Order your middleware something like this:

import thunk from 'redux-thunk';
import { createPromise } from 'redux-promise-middleware';

import {
  middleware as requestsMiddleware
  PENDING, RESOLVED, REJECTED
} from 'redux-rad-requests';

// order matters here!
const middleware = applyMiddleware(
  thunk, // redux-thunk
  requestsMiddleware(), // redux-rad-requests
  createPromise({ // redux-promise-middleware
    // redux-promise-middlware uses slightly different names by default.
    // Here you can match the same status strings used by redux-rad-requests.
    promiseTypeSuffixes: [PENDING, RESOLVED, REJECTED],
  })
);

const store = createStore(reducers, middleware);

Now your action creators can look like this:

function releaseTheHounds () {
  return dispatch => dispatch({ // <-- redux-thunk magic here
    type: RELEASE_THE_HOUNDS,
    meta: { requestId: RELEASE_THE_HOUNDS }, // <-- redux-rad-requests magic here
    async payload () { // <-- redux-promise-middlware magic here
      await dispatch(openGate());
      const hounds = await fetchHounds();
      return hounds;
    },
  });
}

Contributing

Just do this please:

npm test
npm run lint

Did you know there's two different ways of spelling canceled? English is dumb, but we do it the American way. :us: