mobxjs / mobx

Simple, scalable state management.
http://mobx.js.org
MIT License
27.46k stars 1.77k forks source link

Preventing unnecessary updates. #60

Closed dschalk closed 8 years ago

dschalk commented 8 years ago

My monad project running at http://transcendent.ninja (code repo at https://github.com/dschalk/javascript-monads and https://github.com/dschalk/mobservable-monads) is coming along better than I dared hope. Lately in my demonstration, I have been updating the DOM with forceUpdate instead of Mobservable or setState. Here is the third paragraph of README.md at https://github.com/dschalk/mobservable-monads:

"Still, I am uncomfortable with having to repeatedly call ".bnd(refresh)". I would like to use Mobservable again, but I don't want it to try to perform updataes at every link in a chain when all I care about is the value of the last monad in the chain. That happens when monads in a chain hold values for a final computation. The residual values in the monads along the chain are of no interest in such a case, although the values of those same monads might be essential in other computations. Currently, I get render() to execute only when I want it to, but the re-render renders things that didn't change, and that squanders resources. I wonder how hard it would be to cause Mobservable to remain dormant until something like "mobservable.refresh()" is called. Hmmm? Michel Weststrate, here comes Issue # 60."

I know my idea is contrary to the usually desirable automatic update feature. Is my concern about Mobservable wasting resources on unnecessary updates valid? I'm thinking of something vaguely like React.shouldUpdate. It would be a function in the Mobservable API that could shut off "observe" for all but one or more designated entities. What do you think?

The second example at mobservable-monads illustrates my concern. The code is:

onClick={() => {mM1.ret(2)
 .bnd(mM2.ret)
 .bnd(square)
 .bnd(mM3.ret)
 .bnd(square)
 .bnd(mM4.ret)
 .bnd(square)
 .bnd(refresh)  }}

Clicking the button causes all four monads to display. I could have interspersed ".bnd(refresh) between every line and gotten the same result. Instead, I call refresh() once, at the end, and all the updates appear in the right column. If my monad values were observable, I wouldn't need to call refresh(), but would mobservable perform four updates, even though one would suffice?

mweststrate commented 8 years ago

Hi David,

Apologies for the late response.

I didn't look in your source yet, but did you try using transaction? It postpones updates until the end of a block. I think that is exactly what you need here. See http://mweststrate.github.io/mobservable/refguide/transaction.html.

dschalk commented 8 years ago

Perfect!

React wasn't very efficient for my little monad demonstrations, especially since I wasn't using the state or props objects and frequently called React.forceUpdate. Currently, I am using snabbdom and I am very pleased with it. I get DOM updates whenever I like by forcing virtual dom diff & render, which is standard practice in snabbdom. I continue to say good things about mobservable, and it is definitely my goto library for reactive-observable functionality.

If you want to see snabbdom in action, go to http://schalk.net:4001 . The repo is at https://github.com/dschalk/fun-with-monads .

mweststrate commented 8 years ago

Cool :) didn't know snabbdom, virtualDOM libs keep popping up :)

dschalk commented 8 years ago

Ooops! Wrong URL.

I referred you to the wrong address. The correct address for "Fun With Monads" is http://schalk.net:4001. I corrected it above. 4002 is where I am working on Websocket Monads.