Closed ccapndave closed 9 years ago
Ah, ignore this. I just figured out that its a BehaviourSubject (and now I understand why!), so I can type it as Rx.BehaviorSubject<P>
, where P is the property type.
Exactly.
In addition, I think it's better to type it as Rx.Observable<P>
since you're not going to modify the properties' state by using subjects.
Also, we're going to improve the documentation, soon. Sorry that didn't make it clear on how to build components in Cycle-React :p
Thanks for your response. I am still pretty confused about which bits of the framework want Observable
s and which dont. For example, right now I am trying to make a super-simple example to try and understand things, where the top-level model is made up of a loaded json file, and a constant value.
I'm very unclear as to what the model
function is supposed to return. Since this is going to encapsulate the state of the whole app it needs to have lots of sub-models. Should it return a single Observable containing this app state, or should it return an object containing one Observable per bit of state (i.e. per sub-model)?
And when this model (or parts of it) eventually make it into a component, should it still be an Observable or does it get re-wrapped automatically in the h/component function?
There is some very strange code below (I know it doesn't work and the types are all confused, but its just to show the kind of direction I was going in).
Help!
applyToDOM('#app', (interactions: any) => view(model(intent(interactions))));
function view(model$: Rx.Observable<Model>) {
return model$
.map(model => model.course$)
.defaultIfEmpty(null)
.do((x: any) => { console.log("Got a change:"); console.log(x); })
.map((x: any) => h('div', {}, 'Test test'));
}
interface Model {
course$: Rx.Observable<Course>
other$: Rx.Observable<number>
}
function model(intentions: any) {
// A stream to load some json
const course$ = Rx.Observable
.fromPromise(fajax.get('content/menu.json'))
.map<Course>(result => result.body.courses[0])
.shareReplay(1);
// The number 1!
const other$ = Rx.Observable.just(1);
// This returns a single observable containing the Model (which obviously doesn't work because the Model expects an object containing observables)
return Rx.Observable.combineLatest(
course$,
other$,
(course$, other$) => ({ course$, other$ })
)
}
function intent(interactions: any) {
return { }
}
I'm very unclear as to what the model function is supposed to return. Since this is going to encapsulate the state of the whole app it needs to have lots of sub-models. Should it return a single Observable containing this app state, or should it return an object containing one Observable per bit of state (i.e. per sub-model)?
I think both are ok. But, I would prefer having different observables for different sub-models. And combines them by using combineLatest
for the View.
And when this model (or parts of it) eventually make it into a component, should it still be an Observable or does it get re-wrapped automatically in the h/component function?
Cycle-React itself doesn't wrap your values into observables automatically. And I think you should send the plain value instead of observable to components because it makes more sense. You defines the component class by creating an observable, and use the component by sending values into its props
. For example:
https://github.com/pH200/cycle-react/blob/master/examples/many/many-component.js
https://github.com/pH200/cycle-react/blob/master/examples/many/many-view.js
And I can't understand what's the question here from your example code. We can obviously have a model that is a single observable.
The
properties
object given as the second parameter ofdefinitionFn
has an api usingget
to get hold of the Observables inside. Is there a reason that properties can't be a plain Javascript object with the properties on it?I ask because I am experimenting with using cycle-react with Typescript, and one of the nice things is having a well defined interface for component properties, but of course this only works with real objects.