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

in-flux

v1.0.6

Published

Flux-based partial routing solution

Downloads

43

Readme

in-flux

Circle CI Coverage Status Dependency Status devDependency Status

Flux-based partial routing solution

Not a replacement for react-router. Could be used as addition to it. Or standalone.

WARNING Work in progress, though most of the functionality is there.

See issues for more info on what is going to happen.

Idea

The idea of partial routing is coming from the need to track state of independent components in the URL.

Commonly used routers are mostly hierarchical. The great example of such a router is react-router. Unfortunately it is not possible to store component's state independently from the other component in a different "branch" of hierarchy.

They work perfectly for most of the UIs. But as soon as we are trying to build a complex UI with multiple independent components and each of those has own state you would like to preserve, it becomes a challenging task. InFlux was created to provide a simple way of keeping such state in the URL with query params.

Here is an example of such interface.

  1. Chart block, which can be switched from bar to pie
  2. Filter block, that can be opened or closed
  3. Data panel with two tabs: sources and destinations
+------------------------------------------------------------------------------+
|  App "/app"                                                                  |
|                                                                              |
|  +------------------------------+  +---------------------------------------+ |
|  |  chart                       |  |  filter                               | |
|  |  [->bar] [pie]               |  |  [->opened] [closed]                  | |
|  |                              |  |                                       | |
|  |                              |  |                                       | |
|  |                              |  |                                       | |
|  |                              |  |                                       | |
|  |                              |  |                                       | |
|  +------------------------------+  +---------------------------------------+ |
|                                                                              |
|  +---------------------------------------------------+                       |
|  |  data                                             |                       |
|  |  [->sources] [destinations]                       |                       |
|  |                                                   |                       |
|  +---------------------------------------------------+                       |
|                                                                              |
+------------------------------------------------------------------------------+ 

As you can see each of these blocks has its own independent navigation and, for example, Filter can be closed or opened independently from currently displayed Chart type or Data tab selected.

  1. We can always keep the state of each block, but you will loose that state on page refresh.
  2. We can keep their states in some specialized Flux Store and cache in localStorage or even user settings in database on the server. But we are losing ability to share this page with someone else (unless we have some special "copy/paste state" functionality)
  3. At last we can keep state of each component in the URL as query parameter, which solves both problems. Current URL will be: /app?chart=bar&filter=opened&data=sources

Key feature is to update all links on the page if any of visible blocks changed its state. If lets all links to stay links, so it is possible to open link in a new tab, for instance. It is fixed by InFlux.

Minimal Example

import React from 'react';
import {InFlux, Url, LocationHtml5} from 'in-flux';


const Baz = React.createClass({
render() {
  const {value} = this.props.inFlux;
  return <h1>{value && value.toUpperCase()}</h1>;
}
});

const App = React.createClass({
render() {
  return (
    <div>
      <LocationHtml5 />
      <Url query={{baz: 'foo'}}>Foo</Url> | <Url query={{baz: 'bar'}}>Bar</Url>
      <InFlux config={Baz} namespace="baz" />
    </div>
  );
}
});

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

foobar.gif

You can run the Minimal example with npm run foobar, it is shipped with the source code.

Quick-start

Quick-start is a step-by-step walk-through to implement UI based on ASCII example from above.

1. Install in-flux from npm

npm install --save in-flux

2. Add App and main blocks: Chart, Filter, Data

import React from 'react';

const Chart = React.createClass({
render() {
  return <h2>Chart</h2>;
}
});


const Filter = React.createClass({
render() {
  return <h2>Filter</h2>;
}
});


const Data = React.createClass({
render() {
  return <h2>Data</h2>;
}
});


const App = React.createClass({
render() {
  return (
    <div>
      <Chart />
      <Filter />
      <Data />
    </div>
  );
}
});

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

3. Add second-level blocks (not yet used for now)

const ChartBar = React.createClass({
render() {
  return <h3>Bar</h3>;
}
});

const ChartPie = React.createClass({
render() {
  return <h3>Pie</h3>;
}
});

const FilterClosed = React.createClass({
render() {
  return <h3>Closed</h3>;
}
});

const FilterOpened = React.createClass({
render() {
  return <h3>Opened</h3>;
}
});

const DataSources = React.createClass({
render() {
  return <h3>Sources</h3>;
}
});

const DataDestinations = React.createClass({
render() {
  return <h3>Destinations</h3>;
}
});

4. Add InFlux

Wrap each main component, give it a namespace and config

Also render Location provider (LocationHtml5 for History-API links or LocationHtml4 for hash-links).

import {InFlux, LocationHtml5} from 'in-flux';
//...

const App = React.createClass({
render() {
  return (
    <div>
      <InFlux namespace="chart"
        config={{bar: ChartBar, pie: ChartPie}}>
        <Chart />
      </InFlux>
      <InFlux namespace="filter"
        config={{opened: FilterOpened, closed: FilterClosed}}>
        <Filter />
      </InFlux>
      <InFlux namespace="data"
        config={{sources: DataSources, destinations: DataDestinations}}>
        <Data />
      </InFlux>
    </div>
  );
}
});

5. Update your main components with links

Note that wrapper will provide inFlux object to the props of container component.

For now we will use only namespace and Component. First just passes namespace down, second should be rendered wherever we want to have our route handler component.

We will also use Url component provided by in-flux to render dynamic links (they will be updated when any of InFlux blocks changes its state.

import {Url} from 'in-flux';

onst Chart = React.createClass({
render() {
  const {namespace, Component} = this.props.inFlux;
  return (
    <div>
      <h2>Chart</h2>
      <Url query={{[namespace]: 'bar'}}>Bar</Url>
      <Url query={{[namespace]: 'pie'}}>Pie</Url>
      <Component />
    </div>
  );
}
});


const Filter = React.createClass({
render() {
  const {namespace, Component} = this.props.inFlux;
  return (
    <div>
      <h2>Filter</h2>
      <Url query={{[namespace]: 'opened'}}>Open</Url>
      <Url query={{[namespace]: 'closed'}}>Close</Url>
      <Component />
    </div>
  );
}
});


const Data = React.createClass({
render() {
  const {namespace, Component} = this.props.inFlux;
  return (
    <div>
      <h2>Data</h2>
      <Url query={{[namespace]: 'sources'}}>Sources</Url>
      <Url query={{[namespace]: 'destinations'}}>Destinations</Url>
      <Component />
    </div>
  );
}
});

6. PROFIT

Compile your code, the routing is now completed.

Quickstart.gif

NOTE href changes, so we can open link in new tab.

You can run the full Quickstart example with npm run example, it is shipped with the source code.

Development and testing

To run comprehensive example covering all InFlux features, use npm start, which will compile src/example/Example.js

git clone [email protected]:in-flux/in-flux.git
cd in-flux
npm install
npm start

# then
open http://localhost:8080

To run Foobar example, use npm run foobar

To run Quick-start example, use npm run quickstart

Demo

http://nkbt.github.io/in-flux/example

Tests

  1. UI for manual testing - npm start, open http://localhost:8080
  2. Automated tests are in ./test and should be run with npm run test:dev (watch mode)
  3. Coverage report is generated by running npm run test:cov

License

MIT