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-plumbing

v0.1.12

Published

State management/Event publishing framework for React

Downloads

21

Readme

react-plumbing

React-plumbing is an Event propagation a State management framework for react, similar to flux etc.

The services provided by react-plumbing are provided by a container object that wraps your highest-level react object. The Pump object in the react-plumbing framework provides a 'store' object that ecapsulates all application state. All updates to this state should be mediated by the store's action dispatcher. The pump object also takes care of propagating change events to lower-level components via the popagator object. The application data model is exposed the Pump via an object (Site in the example below) that is provided in the Pump's constructor.

import App from './App';
import { Pump, Action, Container } from 'react-plumbing'
import Site from './model/Site'

const pump = new Pump(new Site());

ReactDOM.render(
    <Container 
        store={pump.store} 
        propagator={pump.propagator}>
        <App />
    </Container>, 
    document.getElementById('root'));

React components are wrapped by a HOC so that the store and propagator objects provided to the container are always available:

import { Selector, Action, wrap } from 'react-plumbing'
import { Modal, Button, Panel, Accordion } from 'react-bootstrap'

const site = Action.builder;

function MessagePopup(props, context) {

    function formatMessage(message) { return ( 
        <Panel key={message.id} header={message.text}>{message.detail}</Panel>
    );}

    return (
        <Modal.Dialog>
            <Modal.Header><Modal.Title>Alert</Modal.Title></Modal.Header>
            <Modal.Body> 
                <Accordion>{ props.messages.map(formatMessage) }</Accordion>
            </Modal.Body>
            <Modal.Footer>
                <Button onClick={context.submitter(site.clearMessages())}>OK</Button>
            </Modal.Footer>
        </Modal.Dialog>
    );
}

export default wrap(MessagePopup,  Selector.map( site => { return { messages: site.messages } } ));

In the above example, the Action API is being used to prepare actions to send to the Store via the context.submitter function, and theSelector API is being used to filter information from the Site object and preset it to the JSX view. Action allows you to reference methods and properties of the site object in order to construct complex actions fairly freely:

const site = Action.builder;

function loginAction(form) {
    return site.clearMessages()
        .then(site.authenticate(form.username,form.password))
        .then(site.closePopup().when(site.authenticated));
}

In the above example the loginAction function is creating an action that will call the clearMessages method on the actual Site object provided to Pump, then the authenticate method, and then the closePopup method - but only if the authenticated property of site is true. These methods can return ordinary objects or promises.

The important thing here is that creating an action binds any parameters (form.username and password above) but does not invoke the methods. Method invocation happens only when the action is submitted via context.submitter or context.store.submit.

On completion of the action (including resolving any promises), changes to the site object are broadcast to all components. The Selector object in the above example ensures this the dialog is aware of any changes to the messages property of site.

For this to work, Site (and any sub-objects) need to be immutable. That is, 'setter' methods need to be written to return a new copy of the object (or a promise thereof) rather than change the original. For example, the clearMessages method above would be written:

clearMessages() {
    return Object.assign({}, this, { messages: [] });
}

Action takes care of some of the awkwardness of this when invoking methods on sub-objects of site. For example:

const action = site.screen.cursor.next();

Will ultimately perform something like the following method chain when submitted to the store:

let new_cursor = store.site.screen.cursor.next();
let new_screen = store.site.screen.setCursor(new_cursor);
store.site = store.site.setScreen(new_screen);

Although since the store also takes care of resolving any promises the actual code is somewhat more complicated.