hrx

Overview
Frontend Framework for React and Formula.
Usage
Installation
npm install --save react formula hrx
Examples
Quick start
A minimal hrx app with home and 404 page.
index.js
import React from "react";
import { render } from "hrx";
require("./app.css");
let routes = [
{
path: "/",
component: props => <div>Hello, World.</div>
},
{
path: "*",
component: props => <div>404 NOT FOUND</div>
}
];
render(
{
routes
},
document.getElementById("root")
);
minimal example
With React's render
Render HRX with React's render function.
import { app } from "hrx";
import React from "react";
import ReactDOM from "react-dom";
import routes from "./routes";
let App = app({ routes });
ReactDOM.render(<App />, document.getElementById("root"));
Components
Link Component
A link component to hyperlink your app without annoying page refreshes.
import {Link} from 'hrx'
<Link to="/buckets">Go to my buckets</Link>
Eval Component
The Eval component calculates the result of a formula expression.
import {Eval} from 'hrx'
<Eval exp="SUM(A, B)" values={ A: 2, B: 2 } />
Rule Component
The Rule component renders HTML describing a formula expression.
import {Rule} from 'hrx'
<Rule exp="SUM(A, B)" />
Loadable / loader HOCs
The Loadable HOC works with webpack to split your app into chunks that load dynamically.
import { loadable } from "hrx";
let routes = [
{
path: "/",
component: loadable({
loader: () => import("./home"),
loading: (props) => <div>Loading...</div>
delay: 500
})
}
];
Container Component
The Container component renders the router's current component.
import { Link } from "hrx";
render(<Container />);
Connect Component
The Connect HOC component syncs the store with React state.
import { connect, Container } from "hrx";
connect(Container);
Stores
Router Store
A minimal router, backed by the history API.
import { router } from "hrx";
router.open("/buckets/1");
Use redirect
to modify URL without adding an entry to the history state.
router.redirect("/buckets");
Load routes and related configuration without app
or render
.
import { router } from "hrx";
router.loadRoutes([
{
path: "/",
component: require("./pages/home")
}
]);
Window Store
The window store keeps track of window size and scroll location; syncs with DOM.
import { loadWindowStore } from "hrx";
loadWindowStore();
Custom Stores
Create custom stores to store your app's data.
import { createStore } from "hrx";
createStore(key, reducerOrSpec, actionsAndQueries);
let todosStore = createStore('todos', {
getInitialState: () => []
addTodo: (state, todo) => state.concat(todo),
removeTodo: (state, id) => state.filter(d => d.id !== id)
})
todosStore.addTodo({ id: 1, desc: "Make new framework" })
todosStore.addTodo({ id: 2, desc: "Write killer app" })
todosStore.addTodo({ id: 3, desc: "Analyze competition" })
todosStore.removeTodo(3)
todosStore.subscribe((state, action) => console.log('todos changes', state, action))
todosStore.dispatch('addTodo', { id: 4, desc: "Write product examples" })
createStore( key, reducerOrSpec, actionsOrSelectors )
A store responds to actions by returning the next state.
const inc = 'inc'
import {createStore} from 'hrx';
var store = createStore( "count", (state=0, action) => {
switch (action.type)
case inc:
return state + 1;
case incN:
return state + action.data;
default:
return state;
}, {
inc: (state) => dispatch('inc'),
incN: (state, count) => dispatch('incN', count),
})
store.dispatch('inc')
store.inc()
Optionally, you may define a store with a specification.
const inc = "inc";
import { createStore } from "hrx";
var countStore = createStore("count", {
getInitialState: () => 0,
inc: state => state + 1,
incN: (state, n) => state + n
});
countStore.inc();
countStore.incN(10);
Store Properties
Here is a list of store properties that are part of the public API.
name | comment |
---|
name | The name of the store |
dispatch | Access to dispatch function |
dispatchToken | A number used to identity the store |
subscribe | A function to tegister a listener |
getState | A function to access state |
setState | Replace the store's state |
replaceReducer | Replace the store's reducer |
dispatch( action )
The entry point to effecting state changes in the app is when an action is dispatch.
Dispatch accepts action as object, promise, or type/data; returns promise.
var { dispatch } = require( 'hrx' )
dispatch( { type: 'openPath', '/user/new' } )
.then( action => console.log('Going', action.data) )
dispatch( Promise.resolve({ type: 'get', mode: 'off the juice' }) )
dispatch( 'loadSettings', { a: 1, b: 2 } )
WaitFor Example
import { createStore } from "hrx";
let storeA = createStore(
"a1",
(state = 0, action) => (action.type === "setA" ? action.data : state)
);
let storeB = createStore(
"b1",
(state = 0, action) => (action.type === "setB" ? action.data : state)
);
let storeC = createStore("c1", (state = 0, action, waitFor) => {
waitFor([storeA.dispatchToken, storeB.dispatchToken]);
return storeA.getState() + storeB.getState();
});
getState( )
Returns an object with the store's state by key.
import { getState } from "hrx";
getState();
getStores( )
Returns an object with the stores by key.
import { getStores } from "hrx";
getStores();
replaceState( state )
Rehydrate the root state.
import { replaceState } from "hrx";
replaceState({
MyCountStore: 1
});
subscribe( listener )
Listen to changes to all stores. This will trigger once each time createStore or dispatch is invoked.
var unsubscribe = subscribe( (state, action) => {
// got change
})
// stop listening
unsubscribe()
Please note that action will be undefined when createStore is invoked.