Using mobx with redux in the same project - even in the same component/class
up vote
2
down vote
favorite
A bit of background first:
In in the process of learning react and redux, using Typescript. For components with some kind of application state (rather than pure UI state), I am trying to keep a logical separation between the react components and the underlying logic and state. To that end, for components that work with application state data in some way I have implemented a ViewModel class that is set on the component props and contains the properties and actions that encapsulate that components behaviour. So the ViewModel would (for example), fetch data from the backend and present it is properties to the react component.
One reason for implementing this separation is to ensure that the ViewModel can be unit tested independently of the purely view related aspects contained within the react component. I feel it is important both for the initial implementation and also in future should the logic need to be re-implemented in some future architecture - so that is remains understandable and self contained without a set of "wiring" to a react, redux or mobx specific architecture.
I have implemented this using mobx (@observable and @action decorators in the ViewModel, bound to a component decorated with @observer). All of the state I am implementing so far in this way is just located within the component, or passed down to child components using the ViewModel hierarchy. It is working really well so far, and is a pattern that is easy to apply to new components and won't be a huge leap for devs familiar with knockout etc. which are all positives for my current situation.
However, I am now looking to work with some state that is stored globally so it can be shared between components and persisted. I have been investigating using a redux store for this. I'm really keen not to "throw the baby out with the bath water" and would like to keep using mobx for the "local" application state, and want to keep the ViewModel separation for the reasons previously outlined.
The approach I have implemented so far is to create the redux state properties as @observable fields as usual in my ViewModel class with the @observable decorator. I then subscribe to redux store state changes (by calling store.subscribe()). When the callback passed to subscribe fires (in a mobx action method), I set the value of the @observable fields on the ViewModel with the value retrieved from state. Mobx is smart enough to only re-render if the value set from state actually changed.
When the component that uses the ViewModel fires componentWillUnmount I call unsubscribe() in order to avoid keeping lots of subscriptions alive when they are not required.
So my ViewModel class looks something like this (just outline code here):
import { Unsubscribe } from "redux";
class ViewModel {
@observable
public fieldFromReduxState: string | null = null;
private _unsubscribe: Unsubscribe | null = null;
// Called by the containing component in componentDidMount
public attach() {
this._unsubscribe = store.subscribe(this._updateFromState);
// Initial update from state
this._updateFromState();
}
// Called by the containing component in componentWillUnmount
public detach() {
if (this._unsubscribe) {
this._unsubscribe();
this._unsubscribe = null;
}
}
@action.bound
private _updateFromState() {
const state = store.getState();
// Update local field from state
this.fieldFromReduxState = state.myreducer.statevalue;
}
}
and the components that use the viewmodel look something like (again, just outline code):
interface IMyComponentProps {
viewModel: ViewModel;
}
@observer
class MyView extends React.Component<IMyComponentProps> {
public static defaultProps = {
viewModel: new ViewModel()
}
public componentDidMount() {
this.props.viewModel.attach();
}
public componentWillUnmount() {
if (this.props.viewModel) {
this.props.viewModel.detach();
}
}
// In render, use this.props.viewModel.fieldName
// Bind events to viewModel methods
// In this way, the component retains just the pure view functionality
// and the ViewModel can be tested / re-used in isolation from react
...
}
What I am looking for is insight / advice on those much more experienced with mobx, react and redux as to whether I am likely to hit issues with this implementation, or have been overlooking something key. I'm acutely aware that this is all pretty new to me and I might be creating some nasty issues for myself. I would also be very interested to see if anyone else has come up with good patterns for using mobx together with redux for the different state scenarios in the same project or even component. Seems to me this delivers the best of both worlds with a choice of where the state should live.
I am aware that the idea of moving logic out from the component into a separate ViewModel class is not going to be a favoured approach for everyone, so please humour me a little on that if you can.
I am also aware that many would advocate implementing every single state change (including the results of transient data fetches from a back end) in redux using actions and reducers, but I'm really not keen on going down that route for components without any need for shared state; the mobx model is so simple to work with, particularly for devs who have not got much experience with redux concepts, where a code base is being migrated from earlier technologies such as knockoutjs or there is a general awareness of the MVVM pattern.
So in summary I'm primarily looking for any pointers on pitfalls and problems that my described approach might be leading me into, and any advice on how I might address them if possible.
Sorry for the length of the pre-amble and many thanks in advance for any help or advice offered.
reactjs redux react-redux mobx mobx-react
add a comment |
up vote
2
down vote
favorite
A bit of background first:
In in the process of learning react and redux, using Typescript. For components with some kind of application state (rather than pure UI state), I am trying to keep a logical separation between the react components and the underlying logic and state. To that end, for components that work with application state data in some way I have implemented a ViewModel class that is set on the component props and contains the properties and actions that encapsulate that components behaviour. So the ViewModel would (for example), fetch data from the backend and present it is properties to the react component.
One reason for implementing this separation is to ensure that the ViewModel can be unit tested independently of the purely view related aspects contained within the react component. I feel it is important both for the initial implementation and also in future should the logic need to be re-implemented in some future architecture - so that is remains understandable and self contained without a set of "wiring" to a react, redux or mobx specific architecture.
I have implemented this using mobx (@observable and @action decorators in the ViewModel, bound to a component decorated with @observer). All of the state I am implementing so far in this way is just located within the component, or passed down to child components using the ViewModel hierarchy. It is working really well so far, and is a pattern that is easy to apply to new components and won't be a huge leap for devs familiar with knockout etc. which are all positives for my current situation.
However, I am now looking to work with some state that is stored globally so it can be shared between components and persisted. I have been investigating using a redux store for this. I'm really keen not to "throw the baby out with the bath water" and would like to keep using mobx for the "local" application state, and want to keep the ViewModel separation for the reasons previously outlined.
The approach I have implemented so far is to create the redux state properties as @observable fields as usual in my ViewModel class with the @observable decorator. I then subscribe to redux store state changes (by calling store.subscribe()). When the callback passed to subscribe fires (in a mobx action method), I set the value of the @observable fields on the ViewModel with the value retrieved from state. Mobx is smart enough to only re-render if the value set from state actually changed.
When the component that uses the ViewModel fires componentWillUnmount I call unsubscribe() in order to avoid keeping lots of subscriptions alive when they are not required.
So my ViewModel class looks something like this (just outline code here):
import { Unsubscribe } from "redux";
class ViewModel {
@observable
public fieldFromReduxState: string | null = null;
private _unsubscribe: Unsubscribe | null = null;
// Called by the containing component in componentDidMount
public attach() {
this._unsubscribe = store.subscribe(this._updateFromState);
// Initial update from state
this._updateFromState();
}
// Called by the containing component in componentWillUnmount
public detach() {
if (this._unsubscribe) {
this._unsubscribe();
this._unsubscribe = null;
}
}
@action.bound
private _updateFromState() {
const state = store.getState();
// Update local field from state
this.fieldFromReduxState = state.myreducer.statevalue;
}
}
and the components that use the viewmodel look something like (again, just outline code):
interface IMyComponentProps {
viewModel: ViewModel;
}
@observer
class MyView extends React.Component<IMyComponentProps> {
public static defaultProps = {
viewModel: new ViewModel()
}
public componentDidMount() {
this.props.viewModel.attach();
}
public componentWillUnmount() {
if (this.props.viewModel) {
this.props.viewModel.detach();
}
}
// In render, use this.props.viewModel.fieldName
// Bind events to viewModel methods
// In this way, the component retains just the pure view functionality
// and the ViewModel can be tested / re-used in isolation from react
...
}
What I am looking for is insight / advice on those much more experienced with mobx, react and redux as to whether I am likely to hit issues with this implementation, or have been overlooking something key. I'm acutely aware that this is all pretty new to me and I might be creating some nasty issues for myself. I would also be very interested to see if anyone else has come up with good patterns for using mobx together with redux for the different state scenarios in the same project or even component. Seems to me this delivers the best of both worlds with a choice of where the state should live.
I am aware that the idea of moving logic out from the component into a separate ViewModel class is not going to be a favoured approach for everyone, so please humour me a little on that if you can.
I am also aware that many would advocate implementing every single state change (including the results of transient data fetches from a back end) in redux using actions and reducers, but I'm really not keen on going down that route for components without any need for shared state; the mobx model is so simple to work with, particularly for devs who have not got much experience with redux concepts, where a code base is being migrated from earlier technologies such as knockoutjs or there is a general awareness of the MVVM pattern.
So in summary I'm primarily looking for any pointers on pitfalls and problems that my described approach might be leading me into, and any advice on how I might address them if possible.
Sorry for the length of the pre-amble and many thanks in advance for any help or advice offered.
reactjs redux react-redux mobx mobx-react
Did you notice that in mobx you can create stores and follow a pretty similar pattern like flux but with mutability? Mobx Stores. Why would you add redux if you are already comfortable with Mobx
– DobleL
Nov 22 at 21:05
add a comment |
up vote
2
down vote
favorite
up vote
2
down vote
favorite
A bit of background first:
In in the process of learning react and redux, using Typescript. For components with some kind of application state (rather than pure UI state), I am trying to keep a logical separation between the react components and the underlying logic and state. To that end, for components that work with application state data in some way I have implemented a ViewModel class that is set on the component props and contains the properties and actions that encapsulate that components behaviour. So the ViewModel would (for example), fetch data from the backend and present it is properties to the react component.
One reason for implementing this separation is to ensure that the ViewModel can be unit tested independently of the purely view related aspects contained within the react component. I feel it is important both for the initial implementation and also in future should the logic need to be re-implemented in some future architecture - so that is remains understandable and self contained without a set of "wiring" to a react, redux or mobx specific architecture.
I have implemented this using mobx (@observable and @action decorators in the ViewModel, bound to a component decorated with @observer). All of the state I am implementing so far in this way is just located within the component, or passed down to child components using the ViewModel hierarchy. It is working really well so far, and is a pattern that is easy to apply to new components and won't be a huge leap for devs familiar with knockout etc. which are all positives for my current situation.
However, I am now looking to work with some state that is stored globally so it can be shared between components and persisted. I have been investigating using a redux store for this. I'm really keen not to "throw the baby out with the bath water" and would like to keep using mobx for the "local" application state, and want to keep the ViewModel separation for the reasons previously outlined.
The approach I have implemented so far is to create the redux state properties as @observable fields as usual in my ViewModel class with the @observable decorator. I then subscribe to redux store state changes (by calling store.subscribe()). When the callback passed to subscribe fires (in a mobx action method), I set the value of the @observable fields on the ViewModel with the value retrieved from state. Mobx is smart enough to only re-render if the value set from state actually changed.
When the component that uses the ViewModel fires componentWillUnmount I call unsubscribe() in order to avoid keeping lots of subscriptions alive when they are not required.
So my ViewModel class looks something like this (just outline code here):
import { Unsubscribe } from "redux";
class ViewModel {
@observable
public fieldFromReduxState: string | null = null;
private _unsubscribe: Unsubscribe | null = null;
// Called by the containing component in componentDidMount
public attach() {
this._unsubscribe = store.subscribe(this._updateFromState);
// Initial update from state
this._updateFromState();
}
// Called by the containing component in componentWillUnmount
public detach() {
if (this._unsubscribe) {
this._unsubscribe();
this._unsubscribe = null;
}
}
@action.bound
private _updateFromState() {
const state = store.getState();
// Update local field from state
this.fieldFromReduxState = state.myreducer.statevalue;
}
}
and the components that use the viewmodel look something like (again, just outline code):
interface IMyComponentProps {
viewModel: ViewModel;
}
@observer
class MyView extends React.Component<IMyComponentProps> {
public static defaultProps = {
viewModel: new ViewModel()
}
public componentDidMount() {
this.props.viewModel.attach();
}
public componentWillUnmount() {
if (this.props.viewModel) {
this.props.viewModel.detach();
}
}
// In render, use this.props.viewModel.fieldName
// Bind events to viewModel methods
// In this way, the component retains just the pure view functionality
// and the ViewModel can be tested / re-used in isolation from react
...
}
What I am looking for is insight / advice on those much more experienced with mobx, react and redux as to whether I am likely to hit issues with this implementation, or have been overlooking something key. I'm acutely aware that this is all pretty new to me and I might be creating some nasty issues for myself. I would also be very interested to see if anyone else has come up with good patterns for using mobx together with redux for the different state scenarios in the same project or even component. Seems to me this delivers the best of both worlds with a choice of where the state should live.
I am aware that the idea of moving logic out from the component into a separate ViewModel class is not going to be a favoured approach for everyone, so please humour me a little on that if you can.
I am also aware that many would advocate implementing every single state change (including the results of transient data fetches from a back end) in redux using actions and reducers, but I'm really not keen on going down that route for components without any need for shared state; the mobx model is so simple to work with, particularly for devs who have not got much experience with redux concepts, where a code base is being migrated from earlier technologies such as knockoutjs or there is a general awareness of the MVVM pattern.
So in summary I'm primarily looking for any pointers on pitfalls and problems that my described approach might be leading me into, and any advice on how I might address them if possible.
Sorry for the length of the pre-amble and many thanks in advance for any help or advice offered.
reactjs redux react-redux mobx mobx-react
A bit of background first:
In in the process of learning react and redux, using Typescript. For components with some kind of application state (rather than pure UI state), I am trying to keep a logical separation between the react components and the underlying logic and state. To that end, for components that work with application state data in some way I have implemented a ViewModel class that is set on the component props and contains the properties and actions that encapsulate that components behaviour. So the ViewModel would (for example), fetch data from the backend and present it is properties to the react component.
One reason for implementing this separation is to ensure that the ViewModel can be unit tested independently of the purely view related aspects contained within the react component. I feel it is important both for the initial implementation and also in future should the logic need to be re-implemented in some future architecture - so that is remains understandable and self contained without a set of "wiring" to a react, redux or mobx specific architecture.
I have implemented this using mobx (@observable and @action decorators in the ViewModel, bound to a component decorated with @observer). All of the state I am implementing so far in this way is just located within the component, or passed down to child components using the ViewModel hierarchy. It is working really well so far, and is a pattern that is easy to apply to new components and won't be a huge leap for devs familiar with knockout etc. which are all positives for my current situation.
However, I am now looking to work with some state that is stored globally so it can be shared between components and persisted. I have been investigating using a redux store for this. I'm really keen not to "throw the baby out with the bath water" and would like to keep using mobx for the "local" application state, and want to keep the ViewModel separation for the reasons previously outlined.
The approach I have implemented so far is to create the redux state properties as @observable fields as usual in my ViewModel class with the @observable decorator. I then subscribe to redux store state changes (by calling store.subscribe()). When the callback passed to subscribe fires (in a mobx action method), I set the value of the @observable fields on the ViewModel with the value retrieved from state. Mobx is smart enough to only re-render if the value set from state actually changed.
When the component that uses the ViewModel fires componentWillUnmount I call unsubscribe() in order to avoid keeping lots of subscriptions alive when they are not required.
So my ViewModel class looks something like this (just outline code here):
import { Unsubscribe } from "redux";
class ViewModel {
@observable
public fieldFromReduxState: string | null = null;
private _unsubscribe: Unsubscribe | null = null;
// Called by the containing component in componentDidMount
public attach() {
this._unsubscribe = store.subscribe(this._updateFromState);
// Initial update from state
this._updateFromState();
}
// Called by the containing component in componentWillUnmount
public detach() {
if (this._unsubscribe) {
this._unsubscribe();
this._unsubscribe = null;
}
}
@action.bound
private _updateFromState() {
const state = store.getState();
// Update local field from state
this.fieldFromReduxState = state.myreducer.statevalue;
}
}
and the components that use the viewmodel look something like (again, just outline code):
interface IMyComponentProps {
viewModel: ViewModel;
}
@observer
class MyView extends React.Component<IMyComponentProps> {
public static defaultProps = {
viewModel: new ViewModel()
}
public componentDidMount() {
this.props.viewModel.attach();
}
public componentWillUnmount() {
if (this.props.viewModel) {
this.props.viewModel.detach();
}
}
// In render, use this.props.viewModel.fieldName
// Bind events to viewModel methods
// In this way, the component retains just the pure view functionality
// and the ViewModel can be tested / re-used in isolation from react
...
}
What I am looking for is insight / advice on those much more experienced with mobx, react and redux as to whether I am likely to hit issues with this implementation, or have been overlooking something key. I'm acutely aware that this is all pretty new to me and I might be creating some nasty issues for myself. I would also be very interested to see if anyone else has come up with good patterns for using mobx together with redux for the different state scenarios in the same project or even component. Seems to me this delivers the best of both worlds with a choice of where the state should live.
I am aware that the idea of moving logic out from the component into a separate ViewModel class is not going to be a favoured approach for everyone, so please humour me a little on that if you can.
I am also aware that many would advocate implementing every single state change (including the results of transient data fetches from a back end) in redux using actions and reducers, but I'm really not keen on going down that route for components without any need for shared state; the mobx model is so simple to work with, particularly for devs who have not got much experience with redux concepts, where a code base is being migrated from earlier technologies such as knockoutjs or there is a general awareness of the MVVM pattern.
So in summary I'm primarily looking for any pointers on pitfalls and problems that my described approach might be leading me into, and any advice on how I might address them if possible.
Sorry for the length of the pre-amble and many thanks in advance for any help or advice offered.
reactjs redux react-redux mobx mobx-react
reactjs redux react-redux mobx mobx-react
asked Nov 11 at 22:24
fubaar
2,08811619
2,08811619
Did you notice that in mobx you can create stores and follow a pretty similar pattern like flux but with mutability? Mobx Stores. Why would you add redux if you are already comfortable with Mobx
– DobleL
Nov 22 at 21:05
add a comment |
Did you notice that in mobx you can create stores and follow a pretty similar pattern like flux but with mutability? Mobx Stores. Why would you add redux if you are already comfortable with Mobx
– DobleL
Nov 22 at 21:05
Did you notice that in mobx you can create stores and follow a pretty similar pattern like flux but with mutability? Mobx Stores. Why would you add redux if you are already comfortable with Mobx
– DobleL
Nov 22 at 21:05
Did you notice that in mobx you can create stores and follow a pretty similar pattern like flux but with mutability? Mobx Stores. Why would you add redux if you are already comfortable with Mobx
– DobleL
Nov 22 at 21:05
add a comment |
active
oldest
votes
active
oldest
votes
active
oldest
votes
active
oldest
votes
active
oldest
votes
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53253840%2fusing-mobx-with-redux-in-the-same-project-even-in-the-same-component-class%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Did you notice that in mobx you can create stores and follow a pretty similar pattern like flux but with mutability? Mobx Stores. Why would you add redux if you are already comfortable with Mobx
– DobleL
Nov 22 at 21:05