Question on FuncSubject and StateStreamMixin
agrady42 opened this issue · 4 comments
I'm hoping this is a silly question, but I'm having trouble combining FuncSubject and StateStreamMixin when not using ES6 classes (I have other mixins I want to keep using for now). I'm sure the problem is something to do with timing/lifecycle, but I haven't been able to figure it out.
The (overly simple) sample below creates a simple component that should update it's state based on a text input, but I can't figure out how to make my observable available to getStateStream (I've tried making it in componentWillMount with no success, and even getInitialState). It appears that getStateStream is being called before componentWillMount, so the Observable isn't set yet.
Any help would be appreciated, and thanks so much for this library!
var React = require('react');
var Rx = require('rx');
var RxReact = require('rx-react');
var Comp2 = React.createClass({
mixins: [RxReact.StateStreamMixin],
componentWillMount: function() {
this.aChangeHappened= RxReact.FuncSubject.create();
},
getStateStream: function() {
return this.aChangeHappened.map(function(e) {
return {value: e.target.value}
});
},
render: function() {
console.log(this.state);
return (
<div>
<h1>Header</h1>
<input onChange={this.aChangeHappened} />
</div>
);
}
});
And I just realized that the StateStreamMixin
mixin is using getInitialState
, which will be called before my components (since that's how mixins work). So that's why, but I'm still not sure how to fix it. This is obviously more a problem with my knowledge of React, but if you have any ideas, that'd be awesome.
In this situation you don't need StateStreamMixin. You can create the Subject and subscribe to the component in ComponentWillMount and call setState in the subscribe onNext callback. Make sure to clean up subscriptions in ComponentWillUnmount.
var React = require('react');
var Rx = require('rx');
var Comp2 = React.createClass({
componentWillMount: function() {
this.aChangeHappened= RxReact.FuncSubject.create();
this.stateSubscription = this.aChangeHappened.map(function(e) {
return {value: e.target.value}
}).subscribe(function(state) { this.setState(state); }.bind(this));
},
componentWillUnmount: function() {
this.stateSubscription.dispose();
},
render: function() {
console.log(this.state);
return (
<div>
<h1>Header</h1>
<input onChange={this.aChangeHappened} />
</div>
);
}
});
but if you insist on using StateStreamMixin, then:
var React = require('react');
var Rx = require('rx');
var RxReact = require('rx-react');
var Comp2 = React.createClass({
mixins: [RxReact.StateStreamMixin],
getStateStream: function() {
this.aChangeHappened= RxReact.FuncSubject.create();
return this.aChangeHappened.map(function(e) {
return {value: e.target.value}
});
},
render: function() {
console.log(this.state);
return (
<div>
<h1>Header</h1>
<input onChange={this.aChangeHappened} />
</div>
);
}
});
That was quick! Also I should have thought of both of these (I'm probably overthinking a bunch of things trying to learn FRP and where to apply it).
The second option seems nice to keep the state stream nice and separated, but the first seems more flexible and probably a better way to go in the long run.
Thanks a ton!
No problem. Also, check out the RxJS gitter.