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 🙏

© 2025 – Pkg Stats / Ryan Hefner

re-structure

v0.2.3

Published

A pattern for structuring React applications

Downloads

6

Readme

Re-structure

A pattern for structuring React applications. Heavily based on the re-frame ClojureScript project.

The re-frame README pretty much says it all. This is an approximate adaptation of that idea, meant for building JavaScript applications.

Examples

See here.

Run the examples locally:

npm install
npm run examples

Simple time/color example from reagent : http://localhost:8000/simple.bundle

TodoMVC example : http://localhost:8000/todomvc.bundle

Application "pages" example : http://localhost:8000/pages.bundle

Concepts

Application DB

Just like re-frame has one global application db structure that holds the entire application state, re-structure does too. Your application db is just a data stucture that you create and initialize yourself. You can use Immutable.js, which makes rendering more performant, but it's not required; you could use a regular JS object or any other data structure you want.

Once you initialize your db you have to register it with re-structure when bootstrapping your app:

import {initApp} from 're-structure';

// initialize the application db
let db = Immutable.fromJS({
    timer: new Date(),
    timeColor: '#f34'
});

// register application db with re-structure
initApp(db);

// render your app
React.render(<App />, document.body);

initApp accepts an optional second parameter which defines debugging options. If set to true, re-structure will log all db inputs/commands and db outputs/projections to the developer console.

For more control of what is logged, provide a configuration object of the format: {logCommands: true, logProjections: false}. To log a subset of the application db, provide a projection function as the logProjections value:

initApp(db, {logProjections: db => db.get('timer')});

In the example above, the timer value will be logged to the console when it changes.

Projections

Projections are very similar to subs in re-frame. Where in re-frame you would do this:

(register-sub
  :time-color
  (fn
    [db _]
    (reaction (:time-color @db))))

In re-structure you do this:

// project a part of the application db 
export function timeColor(db) {
    return db.get('timeColor');
}

This defines a normal function that takes the current state of the application db as a parameter and returns a "projected" view of it, exactly what the registered sub does in the re-frame example. Note that you didn't have to do anything special like register the function or wrap the result in a reaction.

Views

An example View:

import {timer} from './projections';

// a view is just a decorated React component
export default @View class Clock extends React.Component {
    // declare projections that the view depends on
    static projections = {timer};
    render() {
        {/* the current value of the projection is available as a prop */}
        return <div>{this.props.timer}</div>;
    }
}

Views have one ability that distinguishes them from normal React components: they can render projection values reactively as they change. When a View depends on a projection's results, it declares so in the static projections property. Then, whenever the projection has an updated value (according to ===), the View is automatically re-rendered and the new value is available as a prop with the same name (this.props.timer in the example above). This is along the same lines as how reactions are used in re-frame/reagent.

Beacuse Views are just decorated React components, you can still keep local state, use lifecycle methods, etc.

Projections can also be parameterized with props values:

static projections = props => ({
    page: db => db.getIn(['pages', props.pageNumber])
});

In this example, projections defines a function that takes props as a parameter and defines a page projection which projects a part of the application state (located using the props.pageNumber). Note that the projections function returns an object that looks like a normal projections definition.

Here's how we might declare a projection inline that doesn't need props:

static projections = {
    pageOne: db => db.getIn(['pages', '1'])
};

Commands

A command is a normal function that takes the current application db value and optional parameters and returns a new version of the application db, with changes applied to it. It is similar to an event handler in re-frame.

An example command:

// return a new version of db with an updated timeColor value
export function setTimeColor(db, {color}) {
    return db.set('timeColor', color);
}

To emit a command, you do just that:

import {setTimeColor} from './commands';

let ColorInput = @View class ColorInput extends React.Component {
    static projections = {timeColor};
    render() {
        return (
            <div className="color-input">
                Time Color: <input type="text"
                                   value={this.props.timeColor}
                                   onChange={e => emit(setTimeColor, {color: e.target.value})}/>
            </div>
        );
    }
}