const app = okwolo([target[, window]]);
// target: DOM node
// window: window object can be specified if needed
const okwolo = require('okwolo/standard');
// create an app that does not render (target blob can be added later)
const app1 = okwolo();
// create an app that renders to the body
const app2 = okwolo(document.body);
// create an app that uses a different window object
const app3 = okwolo(document.body, _window);
The app function defines the layout for the application. It is overloaded to also accept a path as first argument in order to easily describe routes.
app(init)
// init: curried element builder function [() => (state) => element]
app(route, init);
// route: string pattern to match paths (same as in express)
// init: curried element builder function [(routeParams) => (state) => element]
const app = okwolo(document.body);
app.setState({
greeting: 'Hello ',
default: 'Hello World!',
});
// render this element if path matches
app('/user/:username', ({username}) => (state) => (
['div', {}, [
state.greeting,
username,
]]
));
// fallback to render this element regardless of route
app('**', () => (state) => (
['div', {}, [
state.default,
]]
));
Sets the state from which layout is created.
The setState function needs to be called in order for the app to render to any target.
app.setState(state);
// state: an object to replace the current state
app.setState(updater);
// updater: function that returns the new state [(currentState) => ... newState]
// will not render until state is set
app(() => (state) => (
['div', {}, [
['h1', {}, [
'Title',
]],
['p', {}, [
'Content',
]],
]]
));
// will throw an error if state has not been set
app.act('ACTION_TYPE');
// will throw an error if state has not been set
app.getState();
// set the internal state
app.setState({});
Returns a copy of the current state.
app.getState();
app.setState([0, 1, 2]);
app.getState(); // [0, 1, 2]
Executes an action on the state.
app.act(type[, params]);
// type: string of the action type
// params: arguments given to the action handler
app.act(action);
// action: function that returns the new state [(currentState) => ... newState]
app.setState({
friends: [],
});
app.use('action', {
type: 'ADD_FRIEND',
target: [],
handler: (state, newFriend) => {
state.friends.push(newFriend);
return state;
},
});
const newFriend = {
name: 'John',
hobbies: ['kayaking', 'cooking'],
};
/* calling an ADD_FRIEND action and passing
the newFriend to the action handler */
app.act('ADD_FRIEND', newFriend);
Undoes the last action (or setState).
app.undo();
app.setState(0);
app.use('action', {
type: 'INC',
target: [],
handler: (state, amount = 1) => {
return state + amount;
},
});
app.act('INC'); // 1
app.act('INC', 3); // 4
app.undo(); // 1
Redoes the previous action.
app.redo();
app.setState(0);
app.use('action', {
type: 'INC',
target: [],
handler: (state, amount = 1) => {
return state + amount;
},
});
app.act('INC'); // 1
app.act('INC', 3); // 4
app.undo(); // 1
app.redo(); // 4
Resets the state history stacks. This will render subsequent undo/redo operations useless unless state is changed once more.
app.resetHistory();
app.setState(0);
app.use('action', {
type: 'INC',
target: [],
handler: (state, amount = 1) => {
return state + amount;
},
});
app.act('INC'); // 1
app.act('INC', 3); // 4
app.resetHistory();
app.undo(); // 4
app.redo(); // 4
Changes the url and renders layout from the new route.
app.redirect(path[, params]);
// path: string of the new pathname
// params: object to be passed to the route handler
app('/home', (params) => (state) => (
['div', {}, [
params.content || 'home',
]]
));
// renders the route and passes it the params
// will also change the browser's url
app.redirect('/home', {content: 'Hello World!'});
Renders layout from the new route.
app.show(path[, params]);
// path: string of the requested route's path
// params: object to be passed to the route handler
app('/home', (params) => (state) => (
['div', {}, [
params.content || 'home',
]]
));
// renders the route and passes it the params
// will NOT change the browser's url
app.show('/home', {content: 'Hello World!'});
Adds a blob to the app and notifies all modules.
app.use('blobName', arg1, arg2, ...);
// blob: the blob to be added
// args: any object supported by the configured blob handler
// use a blob with a target key
app.use('target', document.querySelector('body .wrapper'));
// blob keys can be arrays
app.use('watcher', [
(state, actionType) => console.log(actionType),
(state, actionType, params) => {
if (actionType === 'MY_ACTION') {
console.log(params);
}
},
]);
const plugin = {
name: 'my-middleware-plugin',
middleware: (next, state, actionType, params) => {
if (state.items.length === 0) {
params.empty = true;
}
next(state, actionType, params);
},
};
// named plugins will only be added once
app.use(plugin);
app.use(plugin);
For more information about blobs, visit the dedicated page .