Comments (18)
There was no reason, I just didn't thought about it :)
Great idea, I'll feature this in the next release 👍
from recycle.
Awesome! I'm also think it would be a great thing to not depend on Observable chaining.
Ideally, the developer can just import what they need.
import {filter, map, observe} from 'some-observable-library'
You would then use a compose
or pipe
function to chain them. This keeps from needing to load the entire library. Could recycle just state what observables it needs for internal purposes and expect those passed as standalone functions and then use them in a non-chained style?
import {filter, map, merge} from 'some-observable-library'
Recycle({
adapters: {
main: reactAdapter,
observable: {filter, map, merge}
}
})
By the way, I'd love to contribute to this. Let me know if there's something you want me to work on!
from recycle.
Here's a discussion on the most.js
observable library about a related matter: cujojs/most#20
With some polish, Recycle with preact and most is dreamy.
from recycle.
I don't want the initialization function to be too complicated, because probably most of the people would use just a default adapter.
But, if somebody still wants to chain functions like you suggested, maybe some kind of compose function could be used?
import {compose, filter, map, merge} from 'some-observable-library'
Recycle({
adapters: {
main: reactAdapter,
observable: compose({filter, map, merge})
}
})
Well, creating a new adapter could be something you can work on if you wish :)
preact is a good idea, and probably inferno as well...
I'm currently working on helper library for testing components and didn't yet experiment with new adapters, so I suspect there will be some issues along the way...
from recycle.
I'm working on a proposal for adapters. I'm stuck on this line https://github.com/recyclejs/recycle/blob/master/src/recycle.js#L194
It seems to return a function rather than an instance of Subject
, and my call to filter
breaks because its API is filter(subject, predicate)
. Any thoughts about that?
from recycle.
I might have solved it with this:
if (!(source instanceof Subject)) {
source = of(source)
}
I'm at 13/16 tests passing now.
from recycle.
I'm quite stuck on this one TypeError: this.predicate.call is not a function
I didn't mess with separating out react adapter from rx adapter yet. The O
object is the interface my Recycle is using for observables. https://github.com/m59peacemaker/recycle/blob/adapter-refactor/src/adapter/react-rxjs.js
The application developer would import this to get the Recycle operators. https://github.com/m59peacemaker/recycle/blob/adapter-refactor/src/adapter/rx-add.js
Concerning the ugly, non-chained version https://github.com/m59peacemaker/recycle/blob/adapter-refactor/src/recycle.js#L66, that can be fixed with a pipe()/compose()
function.
subscribe(
filter(
merge()
() => {}
)
)
// becomes something like
pipe(
merge,
filter(() => {}),
subscribe
)
There are several things that can be perfected here, but do you agree with this direction?
from recycle.
Ok, I now see what you are doing. I'm sorry I didn't understand it before...
I thought you were going to do something like this:
export default {
BaseComponent: React.Component,
createElement: React.createElement,
findDOMNode: ReactDOM.findDOMNode,
render: ReactDOM.render,
Observable: O, // custom made observable
Subject
}
Internally, recycle would then use alredy composed version of Observable
and the main recycle function (recycle.js) would not need to change.
If composed in adapter, still you would not have to load entire library but it would be composed with passed functions that you need. Actually, in a similar way it is done by default with RxJS.
But maybe I'm missing something? Is there a reson this couldn't be done in adapter?
As for tests, sadly it still not all covered yet, so even if you got 16/16 there could still be issues. Sorry about that, I'm working on it :)
from recycle.
I'm a decent example of the problem. I can implement prototype chaining, but I don't like it and I haven't done it much, so it is a bit of a hassle. There may be other developers that want to contribute, but aren't capable of chaining or understanding it. So, forcing the adapter to conform to a chaining API introduces problems and I don't see any benefit. Using a pipe
function is just as nice as chaining. A library like flyd
doesn't have chaining at all, so it would have to be needlessly implemented in a flyd-adapter just for Recycle to have the chaining syntax internally, rather than using pipe
.
I wouldn't put additional fluff into the adapter spec just for this in Recycle's internals:
merge().filter().subscribe
// vs
pipe(merge, filter, subscribe)
from recycle.
I might have missed one of your points earlier.
I thought you were going to do something like this:
export default {
BaseComponent: React.Component,
createElement: React.createElement,
findDOMNode: ReactDOM.findDOMNode,
render: ReactDOM.render,
Observable: O, // custom made observable
Subject
}
That is basically what I did. I just renamed Observable
to O
for convenience. Maybe some of the confusion is because you're thinking very Rx spec whereas I suggest generalizing a little more.
Your thought seems to be:
Recycle uses Rx, so if you want it to use something else, write an adapter to translate that into Rx spec.
My thought is:
Define a generalized spec for what Recycle uses, and then write an adapter from your desired stream library into that spec. This is what cycle.js does. You could then choose a subset of Rx (just the needed operators) as Recycle's observable spec and that would technically fit my philosophy on the matter. However, I am contending that a spec that includes chaining is limiting for no benefit, so something more general and simple than Rx is ideal.
from recycle.
I see what you mean.
The truth is that I didn't yet use library providing an observable object that is not providing its operators like RxJS. But besides RxJS I've used only xstream.
Also, tc-39 proposal for Observable which may be added in ECMAScript is using RxJS as its implementation, so I just used that as default, because I figured map
, filter
and other proposed operators will be standards just as map
or filter
operators are standards for an Array.
That said, I'm not against your idea of implementing it like you suggested, just as long as there is no need for additional boilerplate code application developers needs to write.
For example, sources.childrenActions
which is an Observable passed in component actions is usually used with operators like map
and mapTo
. Since you don't wish to create this kind of Observable object in adapter, does that mean we should create it in recycle main function in order to be used?
Or shoud application developer use some kind of compose operator similar to xstream like this:
actions (sources) {
const button = sources.DOM.select('button')
return [
button.events('click')
.compose(mapTo({ type: 'buttonClicked' }))
]
}
opposed to
button.events('click')
.mapTo({ type: 'buttonClicked' })
}
from recycle.
Interesting. I would rather Observables not be implemented in ECMAScript, but if that is likely to happen, it is worth taking into account. I will reflect on that.
As to the usage in the application code, that is up to the adapter the developer chooses. My personal choice of adapter will likely use flyd
, and so there won't be chaining. Recycle's contract to the developer would be that it provides those observables. What kind of observable would be up to the adapter.
With an Rx adapter, prototype chaining will be implemented, but mapTo
won't exist on it by default, because Recycle doesn't need it. The application developer would add to Observable what they need.
// main.js
// make more operators available to the whole application
import 'rxjs/add/operator/mapTo'
But, I would suggest adding them in the files that use them for the sake of dead code elimination:
// some-component.js
import 'rxjs/add/operator/mapTo'
button.events('click')
.mapTo({ type: 'buttonClicked' })
// if this file is removed and no other files use `mapTo`,
// `mapTo` is no longer included in the application at all. That is good!
A flyd
adapter would not deal with any of that stuff. flyd streams are functors, so anything that can operate on functors will work. Ramda is a popular choice. If you look at the ramda docs, you will see it has a ton of functions. With a stream that is a functor, those functions are able to operator on the stream right out of the box. So, button.events('click')
returns a stream/functor, and then the developer can do anything they want with it, like a bunch of ramda transforms with compose/pipe.
from recycle.
I agree with you. Current recyle API is not good enough to provide a stream library that different from RxJS. In addition to all the operators that should be passed as functions, Subject
should also probably be replaced by something like makeSubject()
(as in cycle.js)
This is quite a change and I would love for recycle to be that flexible.
But I won't do it right away though. Because, even though I make my way around with RxJS, I'm not an expert and I'll need help with abstracting it good enough for all stream libraries.
So, for now I must focus on making a current version stable enough. I want to first write tests for all the existing examples and try to get 100% of coverage. Then a switch to something you suggest would be easier.
To make it easier for me to understand, could you please write an example on how would you write your component (a simple click counter maybe) if flyn adapter is working?
Also, just to be clear when it comes to RxJS adaper - currently, Rx adapter is working as you described. Most of the operators do not exist by default because Recycle doesn't need them, but they can be added. Example of that is Autocomplete implementation.
The only difference is that even though they are not used in recycle itslef, I have included following operators (they help in reducing boilerplate code and are very lightweight): mapTo
, do
(used for debugging) and recycle specific adapters which, by the way, should probably be a part of an adapter and not in recycle itself (I will revisit this issue).
from recycle.
I've had another idea that might work as well. Recycle could use Rxjs internally (just 7kb if you only import/add what Recycle needs), and then have just a function to translate the streams back and forth. So, when sources are about to go out to the application code RxSources.map(translateFromRx)
and when they are updating back to Recycle from the application code, AppSources.map(translateToRx)
.
By default, the translate function would just be source => source
since it's already Rx :)
Could that work? It's simple, but probably hurts performance doing all the back and forth between streams, I bet. Just a thought.
from recycle.
I guess it could work, but it seems to me that could be done as a separate project. Again, I'm really not an expert for reactive libraries since I used just Rx and xstream...
I don't understand what do you mean by "recycle could only import/add what it needs". What exactly is currently imported from RxJS that recycle is not using (apart for mapTo
operator)?
from recycle.
It doesn't. I'm sorry. I didn't mean to sound like I was saying it does. I suppose I added a detail that could have just been assumed. I was just saying, in that approach, you would just import Observable stuff directly, instead of having it passed in by an adapter. I like the simplicity there, but it's probably too costly in performance to translate the streams back and forth. Are you good at benchmarks? It would be easy to try it out. I can make a commit on my fork that is close to ready for that.
from recycle.
Ok, I asked because you said it would take 7kb but I'm pretty sure it's heavier then that currently...
Unfortunately no, I'm not good with benchmarks. I defenitely plan to test it out, when I find the time :)
But for your idea of "translating streams", maybe you don't even need recycle to test it out? If RxJS has its benchmark tests, you can maybe use those that are previously transformed with your library?
Neverthelss, when recycle benchmarks are ready, I'll let you know.
from recycle.
As you can see, there was quite some changes today.
There is no adapter anymore. I think there is really no point of connecting everything manually.
But, recycle main function didn't change much, I just imported all in index.js
(which has about 40 lines of code) so it's still easy to switch libraries
from recycle.
Related Issues (20)
- Benchmark testing HOT 1
- get Recycle on cdnjs :D HOT 1
- About the old versions HOT 3
- SSR? HOT 27
- Why you removed adapters? HOT 4
- warning with version v2.2.1 on next.js HOT 3
- umd build depended on unix machines
- Error when trying to use .withLatestFrom inside effects of a component HOT 2
- State seems shared by component instances HOT 3
- sources.className doesn't work if selected element has multiple classes HOT 1
- Typescript support?? HOT 3
- Use this.setState instead of this.state HOT 4
- sources.select doesn't work in React Native elements HOT 10
- State of this project HOT 1
- i like the `storePath` feature
- what's prevenging Recycle from being just a collection of standard React components? HOT 5
- i think u should remove the information about the `jsx` param in Hello World HOT 2
- Updating docs structure
- Redux plugin HOT 2
- Helper lib for easier unit testing HOT 2
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 recycle.