Comments (9)
I'll read about those links, and try to help if I can!
from router5.
@ArnoBuschmann nope, I'm not working on it, go ahead :)
from router5.
I've been writing a driver for page.js, but I'm thinking about switching it to use this instead.
from router5.
@bcoop713 Interesting as well, have you published it somewhere?
@staltz Haha yes, every Cycle dev should write a driver some day, right? Let's see how far I can get. Next week I'll have time to look at it.
@troch Thanks for creating router5 as it fits nicely to the reactive programming landscape. How comes you added 5 to its name?
from router5.
@ArnoBuschmann you're welcome. I added a 5 because of HTML5. I wanted to keep it simple and well... that stayed. Way better than other ideas which involved trying to fusion "functional", "reactive" and "router" in one word = "frouter" 😁.
from router5.
I've whipped up a Router5 driver for Cycle. It's a first version, and may be buggy, but it could serve as a starting point?
I've implemented it as a source/sink driver. Synchronous state-mutating methods which do not return a significant value, and asynchronous methods which do not require a callback can be called as sink requests by dispatching an array, the first element of which is the function to call, and subsequent elements for each argument. Asynchronous methods which are suitable as observable sources, ("start", "addListener", etc.) are wrapped as functions on the response source object.
Examples:
// source:
let navigateHome$ = responses.router
.addNodeListener('home')
.doOnNext(({ toState, fromState }) => {
// do stuff here
});
// sink:
return {
routing: Rx.Observable.just(['navigate', 'home']);
}
// or just:
return {
routing: Rx.Observable.just('start');
}
Implementation:
'use strict';
import {Router5, RouteNode} from 'router5';
// The set of valid sink functions includes synchronous state-affecting router functions that do not require a callback
// and which do not have a significant return value other than the router object itself.
const validSinkFuncs = ['add','addNode','canActivate','deregisterComponent','navigate','registerComponent','setOption','start','stop'];
function validateAndRemapSinkArgument(arg) {
if(!arg || !arg.length) {
return null;
};
if(typeof arg === 'string') {
arg = [arg];
}
else if(!(arg instanceof Array)) {
throw new Error('A Router5 sink argument should be a string or an array of arguments, starting with a function name');
}
if(validSinkFuncs.indexOf(arg[0]) === -1) {
throw new Error(`"${arg[0]}" is not the name of a valid sink function call for the Router5 driver`);
}
if(typeof arg[arg.length - 1] === 'function') {
throw new Error('Router5 invocations specifying callbacks should be made using the source (responses) object');
}
return arg;
}
function createStateChange$(router, fname, args) {
return Rx.Observable.create(observer => {
try {
router[fname].apply(router, args.concat((toState, fromState) => {
observer.onNext({ toState, fromState });
}));
}
catch(e) {
observer.onError(e);
}
});
}
function createDone$(router, fname, args) {
return Rx.Observable.create(observer => {
try {
router[fname].apply(router, args.concat(() => {
observer.onNext(true);
observer.onCompleted();
}));
}
catch(e) {
observer.onError(e);
}
});
}
export function makeRouterDriver(routes, options) {
let router = new Router5(routes, options);
// The request stream allows certain synchronous [compatible] methods to be called in the form ['funcName', ...args].
return function(request$) {
request$
.map(validateAndRemapSinkArgument)
.subscribe(
([fname, ...args]) => router[fname].apply(router, args),
err => console.error(err)
);
return {
start: (...args) => createDone$(router, 'start', args),
addListener: (...args) => createStateChange$(router, 'addListener', args),
addNodeListener: (...args) => createStateChange$(router, 'addNodeListener', args),
addRouteListener: (...args) => createStateChange$(router, 'addRouteListener', args),
navigate: (...args) => createDone$(router, 'navigate', args)
};
}
}
from router5.
At first inspection, looks good to me.
I feel uneasy with routes
given to makeRouterDriver(routes, options)
because routes
is code for business logic, and the place for that is main()
, not driver configuration, but I doubt there would be a neat driver API for router5 that would avoid such configuration makeRouterDriver(routes, options)
due to the way router5 is.
By the way, we should probably move some of this discussion to https://github.com/cyclejs/cycle-core/labels/drivers, and keep an issue here only if docs for integration with Cycle.js need to be written.
from router5.
@axefrog thank you for getting started on this.
@staltz do you mean you would prefer a driver which is not instance specific? Or makeRouterDriver
should take a router instance?
from router5.
Added an update here: cyclejs/cyclejs#159 (comment)
from router5.
Related Issues (20)
- router5-plugin-browser base is case-sensitive
- TypeError of router5-transition-path HOT 2
- Unhandled promise rejection Error: Alias is already defined in route node in legacy Edge
- Integration(solid-js): reactivity of instance methods, getState vs subscribe's route, etc
- GitHub Pages and router5(+react) HOT 1
- Is non-latin letters are supported in the "path"?
- Remove the routes HOT 1
- Are arrays allowed as route params? HOT 1
- Improve type definitions
- Listeners plugin exposes incorrect typedefs HOT 1
- How to dynamically change base path on browserPlugin
- roadmap? HOT 2
- How can can pass query params to Link by react-router5? HOT 1
- Feature request on Navigation HOT 5
- BUG: errors handling unicode emoji
- QUESTION: Can I use the browser plugin but have each route specify when to use pushState vs replaceState? HOT 2
- Is this project abandoned? HOT 1
- There is an error in the areStatesEqual method
- Anyone interested to keep the package maintained? HOT 1
- cloneRouter() uses same root node
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from router5.