Hacker News new | past | comments | ask | show | jobs | submit login

Frankly, S.js looks better. Simple and performant.



Slightly confusing api, no structural comparison, no adapters for popular frameworks (e.g. S.js-react or S.js-preact), no laziness (computations are recomputed even if they're not requested by reactions).


Why use react when you can use Surplus which is based on S.js? Surplus is the fastest among all of the JS frameworks and supports JSX.

"Slightly confusing" == I'm not familiar with it. Not really an objection.

"No structural comparison": don't know what this is supposed to mean.

Re: laziness, actually redundant recomputations are not performed. Not sure where you go that impression.


I don't want to use surplus because e.g. I want to use well developed UI components or toolkits like blueprintjs, which is implemented on top of React.

Slightly confusing is a real objection. MobX strives to implement transparent reactive programming, where the way you access, update and transform values works exactly like it would with regular objects. S.js has a worse learning curve.

Redundant computations are computed; see: https://codepen.io/anon/pen/vdWomE?editors=0010

even though the completed() computed isn't used anywhere, the reduction is still being recomputed every time todo state changes


> MobX strives to implement transparent reactive programming, where the way you access, update and transform values works exactly like it would with regular objects. S.js has a worse learning curve.

Hardly: reactive values are get/set functions, and you create new ones with S(() => ...). That's it.

MobX's attempt at transparency yields inescapable and surprising corner cases.

> Redundant computations are computed; [...] even though the completed() computed isn't used anywhere, the reduction is still being recomputed every time todo state changes

Incorrect. The todos binding is an SArray not a regular array [1]. See my modified version where I log the events to the console [2].

[1] https://github.com/adamhaile/S-array

[2] https://codepen.io/anon/pen/KQyOyZ


The number of tricky corner cases in MobX are very few. Also, once the implementation switches to proxies the vast majority will disappear.

I'm willing to accept a few corner cases as long as there is a large common subset of functionality that works both with and without a small number of decorators. This can be utilised to write models that can be used in both a reactive and a non-reactive context with a different set of decorators injected in. S.js looks too invasive to do this.

Your codepen has no completed todo count. Why are the recomputations logged every time here?

https://codepen.io/anon/pen/vdWomE?editors=0010

> That's it.

What about the poorly named "S.freeze"


> Your codepen has no completed todo count. Why are the recomputations logged every time here?

Because you can't apply reduce any other way. It's a computation defined over a whole collection. To incrementalize it, you'd need to be able to invert whatever function you're trying to apply in order to arbitrarily undo and redo the operation as elements are added/removed. This is literally impossible in general as not all functions have inverses.

You should also use the SArray methods directly rather than embedding within S(): https://codepen.io/anon/pen/NyXqjB

Edit: you can see a semi-incremental version exploiting map's semantics here: https://codepen.io/anon/pen/KQZddK

If you look at the docs for SArray, you see they describe that map avoids recomputation.

> What about the poorly named "S.freeze"

What would you call it? S.atomic? I don't see how the existing name is particularly unsuitable.


> Because you can't apply reduce any other way.

In mobx, an unused computed will not run or recompute until its requested by a side effect (an autorun reaction, an observer component etc).

Example:

https://jsfiddle.net/ycufg9d3/

We use this to great extent in our application, by only rendering components that are visible in the viewport at the moment.

You can also keep its cached value alive, but not recompute it until needed by implementing a reaction that observes a computed but doesn't request its value. This will keep the entire computation graph cached but idle and partially dirty until the value is requested, at which point only stale dependencies will be recomputed. This can be extremely powerful: for example you can implement a state tree undo/redo by implementing serialize, then observing the serialize computed for the root item without requesting its value (keeping things cached) and only requesting recomputations when certain sufficient number of mutations are made. (with the vast number of reused values being structurally shared between undo/redo states)

> What would you call it? S.atomic? I don't see how the existing name is particularly unsuitable.

Yes atomic would be an improvement. Freeze only makes sense if you are thinking in terms of FRP signals in time, and its unclear whether the abstraction tries to hide its signal underpinnings or expose them (its somewhere inbetween)


No structural comparison:

MobX will stop dependant recomputation if the new value of an intermediate recomputation is equal to the previous value.

You also have the option of using structural equality instead of reference equality (and also you can use any custom equality comparison function)

https://mobx.js.org/refguide/computed-decorator.html#options...




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: