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

react-loader-factory

v1.4.2

Published

A factory for creating custom functional react loading screen components.

Downloads

59

Readme

react-loader-factory

A factory for producing Redux-driven loading screens.

For a version that incorporates ImmutableJS, see react-loader-factory-immutable.

Example

npm install --save react-loader-factory

Say you have an asynchronous request that provides data through Redux to a pure functional component. You'd like to display a loader while waiting for the request, but you don't want to pollute your beautiful pure function.

With react-loader-factory, you can do this instead:

import React from 'react';
import { myAsyncAction } from '../actions';
import loaderFactory from 'react-loader-factory';
import ChildComponent from './ChildComponent';

const actionsList = [myAsyncAction()];
const monitoredStates = ['ASYNC_REQUEST'];
const loaderWrapper = loaderFactory(actionsList, monitoredStates);

const LoadingChild = loaderWrapper(ChildComponent);

const containingComponent = props => {
  // Do whatever you need to do with your usual containing component

  const childProps = { someProps: 'props' };

  return <LoadingChild { ...childProps } />;
}

You'll also need a reducer that tracks which requests are active. Something like this:

export function activeRequests(state = [], action) {
  const newState = state.slice();

  // regex that tests for an API action string ending with _REQUEST
  const reqReg = new RegExp(/^[A-Z]+\_REQUEST$/g);
  // regex that tests for a API action string ending with _SUCCESS
  const sucReg = new RegExp(/^[A-Z]+\_SUCCESS$/g);

  // if a _REQUEST comes in, add it to the activeRequests list
  if (reqReg.test(action.type)) {
    newState.push(action.type);
  }

  // if a _SUCCESS comes in, delete its corresponding _REQUEST
  if (sucReg.test(action.type)) {
    const reqType = action.type.split('_')[0].concat('_REQUEST');
    const deleteInd = state.indexOf(reqType);

    if (deleteInd !== -1) {
      newState.splice(deleteInd, 1);
    }
  }

  return newState;
}

As long as none of the requests specified in monitoredStates have come back with a SUCCESS (or whatever you use to specify a successful request), the loader will continue to display its default throbber, or a throbber prop you pass into the returned loading component.

The guts

  1. loaderFactory(actionsList, monitoredStates) returns a higher-order component that connects to the Redux store and monitors the activeRequests state branch for values it's been told to monitor. It expects activeRequests to have a .some() method to test with. It also takes responsibility for dispatching the Redux actions specified in actionsList exactly once.

  2. If any of its monitored active requests are present, it displays this.props.throbber or a default <div> with a class this.props.throbberClass (or loader layout--flex if none is specified).

  3. If there are no more active requests the wrapped component cares about, the throbber component gets out of the way and returns the originally wrapped component, with all props passed through.

Optional state injector

You can also pass in a function as the third argument to loaderFactory that accepts state as its sole argument. The function should return an object with an array of strings called activeRequests. If any of monitoredStates are present in the array, the throbber will be rendered instead of the dependent content.

const actionsList = [myAsyncAction()];
const monitoredStates = ['ASYNC_REQUEST'];
const loaderWrapper = loaderFactory(actionsList, monitoredStates, function(state) {
	return { activeRequests: state.get('customKey') };
});

Optional state dependency

If you have even more granular requirements for what the state needs to be before the loader should pass the application through, pass in a boolean function of state as the fourth argument to loaderFactory. When this function returns true and the state injector function above return true, the loader will render the wrapped component.

Why a factory?

The factory pattern is needed to set up the connect() call that hooks the component up to your Redux store. There's no way for a component to dynamically connect() itself when evaluated, so the factory pattern gives you that convenience.

Things like this