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

inference

v2.0.96

Published

A dispatcher in a similar vein to Redux.

Downloads

487

Readme

Inference

A dispatcher in a similar vein to Redux.

Why?

To go hand in hand with Reaction. It does away with Redux's centralised state, instead passing updates directly to listeners. It generates updates by applying rules to actions and combining the results in much the same way that Redux employs reducers.

If you like Reaction and Inference then you might like Reaction with Style. Also you should now consider Reaction Hooks in preference to Inference.

Installation

With npm:

npm install inference

You can also clone the repository with Git...

git clone https://github.com/djalbat/inference.git

...then install the dependencies with npm from within the project's root directory:

npm install

You can also run a development server, see the section on building later on.

Examples

There is a small development server that can be run from within the project's directory with the following command:

npm start

The examples will then be available at the following URL:

http://localhost:8888

The source for the examples can be found in the src/examples.js file and corresponding src/example folder. You are encouraged to try the examples whilst reading what follows. You can rebuild them on the fly with the following command:

npm run watch-debug

The development server will reload the page whenever you make changes.

One last thing to bear in mind is that this package is included by way of a relative rather than a package import. If you are importing it into your own application, however, you should use the standard package import.

Usage

Both the combineRules(...) and createDispatcher(...) factory functions can be imported directly.

import { combineRules, createDispatcher } from "inference";

...

See the examples for more information.

Recommended patterns

With React and Redux, typically the forceUpdate() method is called whenever a listener is invoked. This will cause the component's children to be unmounted, with new children being created by way of the component's render() method and then mounted in place of the old ones. It is the render() method that typically queries the Redux state and makes use of those parts of it needed to render its children. A standard pattern is as follows:

class MyComponent extends Component {
  componentDidMount() {
    this.unsubscribe = store.subscribe(() => this.forceUpdate());
  }

  componentWillUnmount() {
    this.unsubscribe();
  }

  render() {
    const state = store.getState(),
          { ... } = state;

    return (

      ...

    );
  }
}

From this it looks as if the component will be re-rendered every time the listener is invoked. In practice, however, React ensures that, to a large extent, components are only re-rendered when necessary. This "diffing" is done under the hood and appears (at least in the author's experience) to work extremely well.

By contrast, Reaction has no diffing algorithm. This means that it is not advisable to re-render a component every time a listener is invoked. Instead, components should typically only change their children in some benign way on these occasions. To facilitate this, Inference passes updates to listeners when they are invoked and these can then be passed on to render() methods directly. A standard pattern, albeit a slightly naîve one, is as follows:

class MyComponent extends Component {
  componentDidMount() {
    this.unsubscribe = dispatcher.subscribe((update) => this.render(update));
  }

  componentWillUnmount() {
    this.unsubscribe();
  }

  render(update) {
    if (update) {
      const { ... } = update;

      // Make benign changes
    } else {
      return (

        ...

      );
    }
  }
}

It is important to emphasise that the render() method has been called directly from the listener instead of the forceUpdate() method. This ensures that the component is not remounted and that the render() method can get away without returning any children. A benign change here means one that has does not add or remove elements from the DOM, instead only adding or removing classes, say, or changing elements' attributes. Reaction provides around a dozen methods for these kinds of changes and it is easy to add others as mixins.

Whilst the above is a perfectly workable pattern, there are times when more flexibility is needed. This is especially true as an application scales. Usually there are a few requirements:

  • Components need to be remounted in response to updates instead of just making benign changes to their children.

  • Updates need to be processed in some way before being passed to the render() method.

It is recommended, therefore, that you create an updateHandler() mixin in order to address these kinds of requirements, invoking it in preference to either the render() or forceUpdate() methods. The above pattern then becomes the following:

class MyComponent extends Component {
  static mixins = [
    updateHandler
  ];

  componentDidMount() {
    this.unsubscribe = dispatcher.subscribe(this.updateHandler);
  }

  componentWillUnmount() {
    this.unsubscribe();
  }

  render(update) {
    ...
  }
}

function updateHandler(update) {

  ...

}

Note that the simple switch on the presence or otherwise of the render() method's update argument has been removed. In fact there should now never be any need to invoke the render() method directly. Here are some examples:

  1. If the component needs to make benign changes to its children in response to updates, do this in the updateHandler() mixin:
function updateHandler(update) {
  const { ... } = update;

  // Make benign changes
}

Experience has taught that this is a cleaner approach because, as already mentioned, it does away with the need for a switch on the presence or otherwise of the render() method's update argument.

  1. If the component needs to be remounted in response to updates, the forceUpdate() method can be called directly from within the updateHandler() mixin:
function updateHandler(update) {
  this.forceUpdate(update);
}

Note that in this case the render() method will be called, and passed the update, during the process of re-mounting. It should therefore return new children when it receives an update.

  1. An interesting and not infrequent corner case, and the only time it makes sense to add a switch for the presence or otherwise of the update argument, is when the render() method does not return any children unless an update is received:
render(update) {
  if (update) {
    const { ... } = update;

    return (

      ...

    );
  }
}

Here the render() method effectively returns undefined when the component is first mounted. Both undefined and null return values are coerced into an empty array, however, so no harm is done.

  1. The updateHandler() method is also the best place to filter updates before passing them to the render() method:
function updateHandler(update) {
  const { page } = update;

  if (page) {
    update = page;  ///

    this.forceUpdate(update);
  }
}

Again it is worth noting that Keeping this kind of logic out of the render() method keeps it simple. Note also that the update argument has been refined before passing it on. Whether or not this is done is really just a matter of taste.

Pre-filtering updates

The subscribe() method can take any number of additional arguments specifying the names of the rules required: For example:

componentDidMount() {
  this.unsubscribe = dispatcher.subscribe(this.updateHandler, "page", "error");
}

componentWillUnmount() {
  this.unsubscribe();
}

Now the updateHandler() method will only be invoked if an update has a defined page or error property and can therefore be written accordingly.

Building

Automation is thanks to npm scripts, have a look at the package.json file. The pertinent commands are:

npm run build-debug
npm run watch-debug

Contact