Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Understanding MobX and when to use it. #199

Closed
AriaFallah opened this issue Apr 18, 2016 · 63 comments
Closed

Understanding MobX and when to use it. #199

AriaFallah opened this issue Apr 18, 2016 · 63 comments

Comments

@AriaFallah
Copy link

AriaFallah commented Apr 18, 2016

Recently having used MobX, I'm trying to reason about why I'm really using it, and trying to truly understand the pros/cons vs redux and cycle.

For redux, I think that it comes down to the fact that most people do not need the number one thing redux has to offer, extreme predicability and extreme testability, because their apps are not complex enough. Thus, when they're writing a bunch of reducers, dealing with extra verbosity, and having trouble grasping the new concepts, only to not reap the benefits, they feel like redux isn't all that useful.

For cycle, I feel like the same way you've written in your docs, most people don't need the complexity and power that RxJS brings to the table over the more simple API MobX provides. MobX also lets you stick to the OOP style that most people are familiar with unlike Cycle, which heavily favors pure composable functions.

Basically MobX lets you write your code as you normally would without forcing you to adopt and learn many new paradigms, and moreover, abstracts away the need to understand your view rendering logic. I think the real power of MobX is the fact that it's just easy.

However, this also makes me wonder.

Redux, ignoring its other limitations and its verbosity, will allow you to write an application that you are familiar with from top to bottom. If you put in the work, it'll be easy to get 100% coverage in tests, and to reason about piece by piece how your program flows.

Cycle despite being more complex, following different paradigms, and needing you to understand RxJS ultimately seems more powerful than MobX if you grasp everything about it.

Do you think the above is accurate?

Also, where do you think MobX fits in when your application grows to be very complex? Like I said above MobX's appeal to me is that it provides similar results to the more complex libraries all while keeping it simple and easy to learn. But when should one pick MobX over Redux or Cycle when they're fully committed to learning and accommodating the complexities of either library? While MobX seems just as capable, the alternatives seem more advantageous if you invest the large amount time necessary to understand them. Is this accurate as well?

An obligatory thank you for writing the library. I'm using it, and enjoying using it. This isn't a critique or anything, but just a deeper dive into understanding its place among other available tools.

@hnordt
Copy link
Contributor

hnordt commented Apr 19, 2016

I don't know Cycle and I have no interest learning it now, so I'll give my opinion on Redux vs MobX.

I've been using Redux since it was released. It's very predictable and testable, but takes a lot time to write a full module, because it needs a lot boilerplate.

Of course you can write helpers to help with less boilerplate, but it still needs boilerplate.

I'm sure you can archieve the same predictability and testability with MobX if you implement it the right way. MobX doesn't force you to implement it in a specific way, you have freedom.

You can even use the same structure as you would use with any Redux app: https://github.com/mobxjs/mobx-react-boilerplate/issues/8

I'm using MobX now because I can write code 3x faster than with Redux, but my codebase still is predictable and testable.

In the end of the day Redux and MobX are just concepts. Choose Redux if you want to have full control over dispatching actions and transforming state. Go with MobX if you prefer to don't manually handle action dispatchments and state transformations.

I think that implemented in the right way, MobX is a natural evolution of Redux, you can trust MobX to manage your state, you just tell what you want, instead teaching MobX how to do it.

I think the main difference between Redux and MobX is that for Redux you need to "teach" how to dispatch actions and transform state, for MobX you just trust that MobX will do a good job, you just tell MobX "do it", and MobX does.

(it's just my personal opinion after using both libraries/concepts in production)

@AriaFallah
Copy link
Author

I've had basically exactly the same experience as you, and I think we've reached the same conclusion.

Although I am curious, how do you test your MobX application?

That's actually what caused me to write this in the first place. I was wondering how testing MobX was different from testing Redux.

Redux is built on the reducers, has time travel and everything is explicit, which is what I think is the only true advantage it has over MobX. This is also it's disadvantage as well interestingly.

So given all that how do you match the predictability of Redux with MobX in your testing?

@hnordt
Copy link
Contributor

hnordt commented Apr 19, 2016

@AriaFallah I'm not an expert with testing, but just try to create your functions as pure as possible, for example:

class MessageStore {
  // bad
  markMessageAsRead = message => {
    if (message.status === 'new') {
      fetch({
        method: 'GET',
        path: `/notification/read/${message.id}`
      }).then(() => message.status = 'read')
    }
  }
  // good
  markMessageAsRead = message => {
    if (message.status !== 'new') {
      return Promise.reject('Message is not new')
    }
    // it's now easily mockable
    return api.markMessageAsRead(message).then(() => {
      // this is a pure function
      // you can test it easily
      return this.updateMessage(message, { status: ' read' })
    })
  }
}

Redux is just javascript, just follow some of the concepts, for example, actions in Redux are the same as MobX, the only difference is the state transformation, for transforming state, create pure functions and pass data around.

@amsb
Copy link

amsb commented Apr 19, 2016

I've enjoyed the aromas emanating from the melting pot of ideas in JavaScript front-end development, but with such a smorgasbord it can be hard to decide what to eat. Redux is built on solid theoretical foundations with a simple essence and a growing community of experienced developers that makes it an extremely compelling candidate for many projects.

That said, my foray into using it left me with a project that felt disjoint in its organization. In particular, I felt this way when coming back to my small project after an absence and needed to mentally trace the thread of logic for an asynchronous action through multiple functions and files. I fully admit that this experience probably reflects my deficiencies more than that of the tools, but nevertheless I was curious to explore a different balance which led me to MobX and my mobx-reactor experiment.

In many ways, my experiment effectively replaces the suite of redux+redux-saga+immutablejs+reselect with MobX (and my library) in a way that is perhaps appropriate for some projects due to their size/scale/velocity/etc. What I learned in doing this is that I ultimately exchanged explicitness (i.e. verbosity/boilerplate) and disjointness (a positive in the context of testability and a negative in the context of organization) with tight organization and bit of implicit "magic" (via MobX managing updates through observables).

One of the things I really appreciate about the Redux approach is the single stream of application events that occur in the form of actions dispatched through a single application store and processed by middleware which furnishes similar opportunities as available during request/response processing of traditional application servers.

@capaj
Copy link
Member

capaj commented Apr 20, 2016

@AriaFallah

Redux, ignoring its other limitations and its verbosity, will allow you to write an application that you are familiar with from top to bottom. If you put in the work, it'll be easy to get 100% coverage in tests, and to reason about piece by piece how your program flows.

You write it like this is a quality that only Redux has. I have to disagree. There is no obstacle at getting 100% coverage for mobX powered app. In fact it is easier to achieve since the amount of code is smaller than with Redux.

@AriaFallah
Copy link
Author

AriaFallah commented Apr 20, 2016

@capaj Ah okay that's good to know.

Like I said above, I haven't done much testing with MobX. I assumed that Redux, where you have to write everything out explicitly, would be easier to test than MobX because there's less magic, but, as you point out, perhaps MobX is easier to test because that magic helps eliminate a lot of boilerplate that made sense anyways so you need to test fewer parts of your code.

Regardless, the whole point of the post is to get perspectives like yours. I'm not trying to peddle everything in the main post as fact like one would in a medium post. I created it as a result of curiosity and confusion about the concepts of MobX and how it stacks up against the other more popular libraries.

@PhiLhoSoft
Copy link

Some input:

  • I know a bit Redux, as I wanted to introduce it to our project. I actually rewrote it in ES5, which made me look into its code (not so big) and to understand how it works. I like the ideas, well explained by Dan Abramov. I finally dropped the idea, partly because of boilerplate, mostly because using a single store of immutable data would be too foreign for my co-workers (and perhaps even for me! I appreciate the ideas, but I have little experience with these fields).
  • I use RxJS in our application, although I can't say I totally master it... Vast API surface! Indeed, as @mweststrate told in a reply (in HN or similar, I can't recall), you can do things similar to MobX in RxJS, but it is a bit convoluted... And as said in the docs, you can freely mix and match both libraries, one for time-driven streams (managing events, etc.) the other for state / data management.
  • I introduced successfully MobX in our application: it adds little boilerplate and feels natural to use. Works well in ES5. What is nice is that it doesn't ask you to structure the application around it! I used it for a specific usage: managing state in each controller (AngularJS) to handle various conditions to disable controls (toolbar buttons, dialog buttons, others) depending on various factors (user input, state of data, waiting for data, etc.).

Testing was not a problem (unlike RxJS parts!): I just have variables, I verify they have the right state on given conditions. That's all.
OK, it changes some things: instead of doing ctrl.observedVar = true for a quick test, I have to set up the variables on which observedVar depends to do the test. Logical.
Also, Jasmine is a bit lost with special MobX objects: its isEqual works well with them, but if the values differ, it reports something like "got { name: (getter) } instead of { name: "foo" }", needing a bit more work to see what went wrong.

Overall, experience with MobX is very good.

@hnordt
Copy link
Contributor

hnordt commented Apr 21, 2016

@capaj @PhiLhoSoft

Would be awesome if you share some of your testing approaches with MobX.

@hellectronic
Copy link
Contributor

@AriaFallah @hnordt Do you have concrete questions in regard to testing?

@capaj
Copy link
Member

capaj commented Apr 23, 2016

@hnordt I have an article on mobx recipes in the making. Will include some samples and showcases on testing. Give me 1-3 weeks, I'll post it then.

@PhiLhoSoft
Copy link

Well, as I wrote, testing wasn't much specific. At least in my use case. I added MobX in a very local way (controller level) in an existing AngularJS 1 application, to replace part of the code.
Not using it as a central store, as it would have been too disruptive. We have already some unit tests (made with Jasmine, run with Karma, classical in the Angular world), not enough because of deadlines and so.
But well, the updates I had to do to accommodate the introduction of MobX were minor, as explained above. That's the beauty of MobX: it is quite transparent... And not opinionated, so we can use it outside of React, in a non pervasive way, my way and not in the way envisioned by the project.

@Keats
Copy link

Keats commented Apr 27, 2016

@AriaFallah posted a short video to some info: https://www.youtube.com/watch?v=83v8cdvGfeA

@AriaFallah
Copy link
Author

AriaFallah commented Apr 27, 2016

@Keats haha yeah, but I figured that since I was just summarizing the information here and not as much in depth I wouldn't promote it myself. I appreciate you posting it though 😄 .

I have to thank @hnordt and @capaj for providing me with a lot of the insight I had in this thread to be able to make the video.

@yelouafi
Copy link

yelouafi commented May 23, 2016

IMO the most fundamental difference between Redux and MobX, from a conceptual POV, relates to the update logic.

In Redux, a Reducer encapsulates all the possible ways in which a piece of state can be updated. i.e. you can't (directly) update that piece of state from outside. And the overall state/reducers is organized around this notion of update logic.

In MobX, the state is managed inside observables, but observables act like free slots which accept data from the outside. So in order to tell how the state held by an observable is updated you need to look to all the actions that update that observable.

Typically some (maybe all, depending on the case) of the update logic can be inside a domain class, making observables private and exposing only getters for observable values and the set of actions that update the private observables. But still the update logic will be spread across multiple actions.

So depending on the case: either Redux or MobX will feel easier. I don't think it's related to the size of an application but more to how complex is the update logic. if a domain class can encapsulate all its update logic, and if the overall behavior of the class can be easy to reason about, then effectively MobX will feel easier than Redux (talking about the models not specific implementations).

However if the update logic of the app is such that it can't be encapsulated inside the domain class (e.g. you can't call the class method directly from you UI callback, or the called action will lead to cascaded calls to other actions in other domain classes), then Redux model will feel more suitable here.

@AriaFallah
Copy link
Author

AriaFallah commented May 23, 2016

@yelouafi

I've never thought about it that way 😮

I do have one question though. When you say:

However if the update logic of the app is such that it can't be encapsulated inside the domain class (e.g. you can't call the class method directly from you UI callback, or the called action will lead to cascaded calls to other actions in other domain classes), then Redux model will feel more suitable here.

Could you elaborate on what you mean by can't call the class method directly from your UI callback, and also why it's easier to use Redux in this case vs MobX? I'm having trouble visualizing what you're saying. Is it that MobX can't wrap all of the update logic in a single place like Redux reducers can?

@yelouafi
Copy link

yelouafi commented May 23, 2016

Is it that MobX can't wrap all of the update logic in a single place like Redux reducers can?

Say for example, you dispatch an action TODO_ADDED and you have 2 reducers : todoList (to add the new todo to some list) )and onBoarding (for ex. to track user progress) which both react to the same action. In the Todo UI, you'll only do dispatch(todoAdded(...)), the store will dispatch the action to all reducers and both reducers will perform the update logic internally.

Now with mobX, imagine you have 2 classes TodoList and OnBoarding which also both watch for todo creations but each has a different update logic. In this case, you'll have to trigger 2 actions from the UI, one for each class, but then you'll have a part of your update logic in the UI. You may also embed the call to OnBoarding inside the TodoList.addTodo(...) method. Or make a supervisor class which encapsulates the whole logic, and then call the supervisor class from the UI but then you'll have those cascaded actions (e.g. you aren't calling OnBoarding.todoAdded(...) directly from the UI)

One may argue that OnBoarding could be made a reaction to TodoList, but what I'm emphasizing here is that we're not interested in reacting to state changes but to the event itself (e.g. we may want to watch for 3 consecutive TODO_ADDED events)

@glenjamin
Copy link

Is it that MobX can't wrap all of the update logic in a single place like Redux reducers can?

I think this is the fundamental difference, most of the rest is just implementation details.

Redux (and flux in general) forces you to write your data updates outside the components at the top of your application, and enumerate all possible updates.

MobX doesn't enforce this, however there's nothing that prevents you from doing it this way.

@AriaFallah
Copy link
Author

@yelouafi

I see. So you're saying that you can't mutate two different domains, Todos and OnBoarding for example, at the same time without using something like computed, which isn't reacting to the event itself, but to the mutation of another observable.

My question would be, couldn't you solve the problem by taking a "redux-like" approach and having a single store at the root that accepts these events?

@yelouafi
Copy link

yelouafi commented May 23, 2016

[Update] @AriaFallah this may answer your last question
I want to add that the 2 approaches are not mutually exclusive: we can have advantage from the 2 words by combining the pros of each approach

  • From Redux the reducer being able to encapsulate all the update logic and not having those 'free slots' (observables)
  • From MobX with the dynamic and self-adjusting dependency model (automatic dep. tarcking) which offers a great way to express reactive computations and also finer grained observation

So what could be the combination Reducer + Observable?

IMO, the question has already been ansewred a long time ago by FRP. I'm not talking about RxJS here because Rx has only one half of FRP: the discrete part which is event streams. The other half is the continuous part known as Behaviors (cf. original paper of Conal elliott on FRP)

A Behavior models also a time varying value. But unlike discrete streams, a behavior has always a value (even from the start). here you can view it like an observable but which can not be updated arbitrarily. When you declare a behavior you must declare its update logic at the declaration. And the update logic can be specified with 2 things: the Event streams which affects the behavior state and the reducer which will handle the event streams)

Here is a simple example of the todos example (I've made this example from a rough sketch but I think the concept could benefit from being implemented in a well tested lib like MobX)

// toggle$, toggleAll$, ... are event streams
function newTodo(id, title) {
  return {
    id, title,
    done: behavior(
      false, // start value
      [ toggle$.filter(eqF(id))   , done => !done ], // reducer for toggle events
      [ toggleAll$                     , (_, done) => done  ] // reducer for toggleAll events
    )
  }
}

export const todoList = behavior(
  [], // initial state
  [
    addTodo$,
    (todos, id) => todos.concat(newTodo(id, editingTodo.value))
  ],
  [ 
    removeTodo$,
    (todos, id) => todos.filter(t => t.id !== id)
  ]
)

// computed property
const allDone = computed(() => todoList().length && todoList().every(t => t.done()))

Like in Redux, you can trigger an update from an event stream and it'll update all the behaviors depending on that event

@yelouafi
Copy link

And of course the other way is also possible. You can embed behaviors in Redux (with some restrictions thou to make serializability/hot reload possible) and implement an automatic dep. model (like observable selectors) on top of that

@AriaFallah
Copy link
Author

AriaFallah commented May 23, 2016

@yelouafi

I actually was looking into something similar recently while looking into FRP. I was experimenting with combining MobX and Most.js to get a mix of the event and behavior/cell streams, but didn't get very far.

I guess my question at this point is that if FRP with both event and behavior streams is the solution, how come it hasn't been created/used yet? Are there any drawbacks?

@yelouafi
Copy link

Cant say this is THE solution, this is just my POV. Many will find no issues on writing code with free observables b/c it maps directly to their mental model. Others will prefer FRP style updates. And domain space can also make either option more appealing

That being said, and although I didnt looked much into different libs I think Bacon.js has a similar concept called Property and also flyd streams may take an initial value.

But AFAIK there is no lib which combines the dynamic dep. model of Mobx/Ko with FRP reactive behaviors.

For example, in Bacon you cant access to the value of a property directly using prop() but you'll have to snapshot it with some event stream.

@yelouafi
Copy link

And I'd just like to add that, in my POV, there is an added value on putting as much as you can of your logic into the 'pure side'. The world of functions is 'eternal': a relation between 2 things is like an invariant captured in your program, insensible to time, and wont be affected by how things get sequenced on the external world (i mean the relation). You can view it like eager (non lazy) mobx derivations which ensure consistency w relation to the event world

@AriaFallah
Copy link
Author

AriaFallah commented May 23, 2016

Forgive me if I'm asking too many questions, but I have a few more.

There is an added value on putting as much as you can of your logic into the 'pure side'

  • When you mention purity, at least in relation to MobX, I think of its emphasis on mutation. Do you think there are any benefits MobX can gain from being more pure/immutable? When I think of immutability, I think of thread safety, which doesn't apply to JS, referential integrity, which MobX already gets through observability, and shallow comparing, which I don't think is all that great. Is there something I'm not thinking about...maybe in a big picture sense?

The world of functions is 'eternal': a relation between 2 things is like an invariant captured in your program, insensible to time, and wont be affected by how things get sequenced on the external world (i mean the relation). You can view it like eager (non lazy) mobx derivations which ensure consistency w relation to the event world.

  • I feel like this answers my question above in a sense, but I don't really have a concrete understanding of what you're trying to convey. I get that you're saying because pure functions are deterministic and referentially transparent, they capture an invariant relationship between their parameters that doesn't depend on anything except their values, but how does that relate to mobx derivations and the big picture in general?

@mweststrate
Copy link
Member

Don't want to interfere to much in this thread, because it is way more interesting to discover how people perceive MobX than having me talking about how I intended MobX ;-).

But the cool thing that @yelouafi is onto here is probably that the behavior objects are observable, trackable and seemingly mutable to the outside world. However to mutate an object, you have to invoke one if its actions which is still a pure function, thereby easily testable, snapshottable and all advantages that come from that. So it moves the whole tracking / observable thing closer to the FP ánd event streams world, but without giving up on referential consistency etc yet (or gaining the general advantages of immutables) (if I see it correctly).

I think indeed this pattern could be built on top of MobX quite easily. Especially with the intercept api in 2.2 with which you can control where and when objects can be mutated and make them immutable for the outside world.

@yelouafi
Copy link

@AriaFallah simply put you can write a program in terms of relation input-output and have the underlying runtime ensure the relation always hold. Actually mobx ensures ref. transparency between obs. and derivations but the part the goes from the event to the obs. mutation is outside of its scope.

I dont emphasize on immutability at this level. In fact the whole purpose of immutabiliy in FP languages is that you cant have ref. Transparency with mutable values. At the 'FRP level' if I can ensure my relations are maintained (ex an observable array propagates change while the underlying raw array us mutated) I'll be fine with it. My goal is not immutability but ref. Transparency.

@mweststrate that would be interesting. If we can ensure trandactional semantics for behavior updates (a root event updates the state in a single transaction like Redux have actually) then I think mobx would make a great complement to actual discrete event stream libs

@mweststrate
Copy link
Member

see transaction?

Op di 24 mei 2016 00:37 schreef Yassine Elouafi [email protected]:

@AriaFallah https://github.com/AriaFallah simply put you can write a
program in terms of relation input-output and have the underlying runtime
ensure the relation always hold. Actually mobx ensures ref.
transparency between obs. and derivations but the part the goes from the
event to the obs. mutation is outside of its scope.

I dont emphasize on immutability at this level. In fact the whole purpose
of immutabiliy in FP languages is that you cant have ref. Transparency with
mutable values. At the 'FRP level' if I can ensure my relations are
maintained (ex an observable array propagates change while the underlying
raw array us mutated) I'll be fine with it. My goal is not immutability but
ref. Transparency.

@mweststrate https://github.com/mweststrate that would be interesting.
If we can ensure trandactional semantics for behavior updates (a root event
updates the state in a single transaction like Redux have actually) then I
think mobx would make a great complement to actual discrete event stream
libs


You are receiving this because you were mentioned.

Reply to this email directly or view it on GitHub
#199 (comment)

@mweststrate
Copy link
Member

mweststrate commented May 24, 2016

@yelouafi didn't test it, but an implementation of behavior with [email protected] would look like this I think:

import {observable, action, asReference} from "mobx"

function behavior(initialState, ...actions) {
    // store state in an observable
    // we use asReference for a one-size-fits-all approach; treat any value as a single atom
    // not using asReference would be slightly efficienter for tracking (e.g. individual properties can be tracked)
    // but would need to deviate per type (e.g. use array.replace, map.merge or extendObservable to merge a new state into the current one)
    const state = observable(asReference(initialState))

    // make sure only our reducers can modify state
    let isRunningReducer = false
    state.intercept(change => {
        if (isRunningReducer)
            return change // OK
        else
            throw new Error("State should be modified by emitting an event")
    })

    state.observe((newValue, oldValue) => {
        // do cool stuff for time travelling, debug tools or similar
    })

    // subscribe to the streams, actions guarantee transaction semantics
    actions.forEach(
        ([stream, reducer]) => 
            stream.subscribe(action(event => {
                isRunningReducer = true
                state.set(reducer(state.get(), event))
                isRunningReducer = false
            }))
    )

    return () => state.get()
}

@luisherranz
Copy link
Member

I've been thinking about this a lot too. I really like the way code is written in Mobx but I prefer the Redux code organisation and pattern (Flux).

A while ago I had an idea to build a redux-like API on top of Mobx. I stopped because first I want to build a big app using redux/redux-saga and another one with mobx, which is what I am doing that right now with two of my projects.

Anyway, I'd love to share my thoughts with you in case they are of any interest. I've been thinking a lot about how the API would look like more than the implementation details, but I think it would be easily built with Mobx v2.

I don't want to hijack this issue so for anyone interested I've created a gist with my latest thoughts. Feel free to let me know what you think:
https://gist.github.com/luisherranz/afc77fe8e74e06dd0ed666a118d5b0ce

My plan is to keep improving and simplifying the API while I gain more and more experience with both Redux and Mobx, always looking for better easy-to-write, easy-to-reason, easy-to-test and no-boilerplate patterns.

@mweststrate mweststrate reopened this Aug 18, 2016
@Kamaraju333
Copy link

@mweststrate can you explain how observable works internally and is state immutable in mobx?

@mattruby
Copy link
Member

Mobx state is not immutable. Here's a video that goes over how mobx works
: https://youtu.be/TfxfRkNCnmk there are many articles that go over how
mobx works.

On Oct 17, 2016 10:47 PM, "Kamaraju prathi" [email protected]
wrote:

@mweststrate https://github.com/mweststrate can you explain how
observable works internally and is state immutable in mobx?


You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
#199 (comment), or mute
the thread
https://github.com/notifications/unsubscribe-auth/AAIrctRRLdWyy37-04EHln2-tL1BJU3Qks5q1EFrgaJpZM4IKFcX
.

@Kamaraju333
Copy link

@mattruby Thanks

@fourcolors
Copy link

@mattruby It would amazing if you could set some type of configuration to tell MobX to work as immutable. Except not immutableJS cause.. ain't nobody got time for that.

@mattruby
Copy link
Member

Check out mobx-state-tree.

On Oct 31, 2016 11:06 AM, "Sterling Cobb" [email protected] wrote:

@mattruby https://github.com/mattruby It would amazing if you could set
some type of configuration to tell MobX to work as immutable. Except not
immutableJS cause.. ain't nobody got time for that.


You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
#199 (comment), or mute
the thread
https://github.com/notifications/unsubscribe-auth/AAIrcrAw_crcmVkcKi18jyPl22OimU9pks5q5hH9gaJpZM4IKFcX
.

@joelday
Copy link

joelday commented Jan 14, 2017

EDIT: Will rearticulate this later once less drunk.

@mweststrate
Copy link
Member

@joelday regarding that last comment; MobX already has Knockout style computed observables? Or am I missing something here?

@frankandrobot
Copy link

The momentum around mobx reminds me of when angular's two way data binding first came out. It really was a joy to use compared to the frameworks of the time. However the honeymoon eventually ended when large real world projects gave birth to the state soup problem. Devolper velocity further decreased whenever you had to open the angular internals, namely the compiler. I'm wondering out loud if developers are still in the honeymoon stage with mobx. Namely, what sorts of problems are encountered with mobx in large, complex apps? Seems too early to tell.

A second issue alluded to earlier is the state soup problem. One way data flow solves it. As far as I can tell, mobx brings it back. There's nothing to keep you from creating an app of interconnected objects with cyclic dependencies, right?

@hccampos
Copy link

@frankandrobot while you can do two-way data binding in MobX, you are not advised to do so. In fact, when using strict mode, all state mutations need to happen in the context of an action which means you can get a clean trace of everything that happened in the program, and why it happened, a bit like Redux. It is just that redux asks (but doesn't enforce) you to always return a new object while MobX lets you modify the state and keeps track of it.

That being said, it is left up to the developer to decide on the best place to put their actions. You can put them all in a single store/service, you can put them in different stores/services based on domain, or you can indeed sprinkle them everywhere and end up with a mess. Redux in this regard is more beginner-friendly (some would say noob-proof) in that it stipulates that all the state mutations always happen in the same place (reducer).

@capaj
Copy link
Member

capaj commented Jan 30, 2017

@frankandrobot

Seems too early to tell.

Have you tried writing a big SPA with MobX? I have and I certainly did not enter state soup problem. I keep my state minimal, derive anything that can be derived. Everyting is fast, smooth, readable and concise.

@marvinhagemeister
Copy link

@frankandrobot While mobx does not actively prevent the user from two way data-binding without useStrict(true) it is highly encouraged to use a one way data-flow like you suggested. Mobx doesn't change that. At work we're using mobx to build an SPA with complex, nested and dynamic forms and mobx has been a lifesaver so far. Even more so for team members who struggle a bit with functional coding style or redux.

@frankandrobot
Copy link

@capaj Any more details about your team? If you're telling me it's a one person team, of course, mobx works! Any framework works when it's only one person. Interested in seeing how the architecture holds up on a good size team (+4) on a large, complex app and over the long term. I've used redux before in this scenario and the architecture held up pretty well. @marvinhagemeister interested to know what your thoughts will be a year from now :-)

@mweststrate
Copy link
Member

mweststrate commented Jan 31, 2017

We are working with ~18 people on a MobX based project for almost 1.5 year now at Mendix. Would not be surprised if Wix, Lyft or Microsoft teams are working with similar sized projects. Don't know much details about those however, as these are internal projects and I am not involved in them. If you search the reactjs reddit you'll find quite some testimonials from big development teams using MobX

Edit: forgot not in a critical place :)

@marvinhagemeister
Copy link

@frankandrobot Our current team for this particular project is around ~8-10 people (some part time freelancers). Perhaps the difference is that the redux community has settled on a few preferred ways of doing things (reselect, redux-saga,...) compared to MobX.

Nonetheless both redux and MobX are excellent for state-management. One can't go wrong with either.

I'm curious to what the future holds as well, especially when Proxy-Objects are supported everywhere (so close!).

@luisherranz
Copy link
Member

Both Redux and Mobx are awesome state managers, but if I would have to bet for the future state manager that'd be mobx-state-tree. It has the best of both worlds (and even more).

@marvinhagemeister
Copy link

@luisherranz That looks very interesting. It's more like an "extension" for mobx though and not a replacement. In our case we've gone with a similar route. Our state has a tree shape and each model has a de-/serialize method which has been great when loading data from an api and constructing models. I'm really excited about the snapshot feature of mobx-state-tree though! That's the only thing I miss with mobx coming from redux.

@hccampos
Copy link

hccampos commented Jan 31, 2017 via email

@marek-sed
Copy link

marek-sed commented Mar 9, 2017

Hi, we are building an app for displaying various data we getter from different IOT devices (sensors, cameras,.. ). Frontend has really minimal logic, basically it just displays data into various sections. And user can create some filters for data. The app is currently in redux but it seems like an overkill and there are some big issues with unecessary rerenders which would require lots of effort to fix. So we want to rewrite it and are deciding between, mobx or immutablejs + some cursor library.

The logic in app is really simple.
apply filter -> fetch data -> merge into state -> react render.

Is mobx a good match for such application, how does it perform when merging large jsons into state.

@mweststrate
Copy link
Member

mweststrate commented Mar 14, 2017 via email

@quangv
Copy link

quangv commented Aug 1, 2017

You can use cycle.js in place of redux/mobx for a React app? I never thought to do this, is there anywhere I can read more about this?

@janaagaard75
Copy link

janaagaard75 commented Jun 24, 2018

@GitCash send 0.02 BCH to @mweststrate

Really sorry for the hideous large banner below. This is first time I'm trying the new GitCash tipping bot, and I wanted to tip my favorite project, but obviously hadn't thought this through. Now this just looks like a bad ad for Bitcoin Cash. :-(

Update: The GitCash bot was banned from GitHub, so the message below has been removed. I also realized that everybody subscribing to this thread got the image in an email. Double bummer.

@GitCash
Copy link

GitCash commented Jun 24, 2018

GitCash Tip Response
@mweststrate

@stale
Copy link

stale bot commented Jun 19, 2019

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests