dy / spect

Observable selectors in DOM
https://dy.github.io/spect
MIT License
76 stars 8 forks source link

Merge `use` and `fx` #71

Closed dy closed 5 years ago

dy commented 5 years ago

For: +use oftentimes requires conditional triggering, eg. i18n must be updated only when lang changes, preloader must trigger only when loading state/attr changes. +fx has the same signature - it passes element as single argument and is called multiple times. +Besides, use doesn't know how to destroy itself, acts like component upgrade. fx would enable natural destructor for it.

The difference now is

$a.fx(() => { // doesn't subscribe to updates of b.state.x $b.state('x') }, [])

~ We could actually declare deps not as a single-time value run, but as observers as well
```js
// that rerenders aspect whenever $doc.attr`lang` changes, not only on a single-time run
$app.fx(i18n, [$doc.attr`lang`]) 
// doesn't make much sense, since anyways that's read internally since that's dep

~ Aspects must not be run, unless any of the deps has changed. We have to be sure there's no vain runs. ~ This way, deps become indicators when the aspect must be run. mount and other lifecycle events become deps. (when html patches/mounts element, it triggers assigned aspects).

Against: ~ there was some argumentation, to be found in issues. Somewhere where we discuss possible ways to trigger rerendering - internal changes, external deps and direct call. ~ not sure how to assign effects via html

Actually, that makes API more elegant and easier to understand. Also that provides more reason to $el.fx call. The question if $el.use or $el.fx name is better for effect. $el.fx feels more familiar.

The other question - how do we assign effects via html - we cannot force unknown els all to be custom elements, because aspects are indestructible.

dy commented 5 years ago

. Now use and fx detach subscribed scopes (use) from gated methods (fx) - fx is guaranteed to run any time use is run. If we merge them, sub-effects can be run on their own, if, for example, the values they read internally, change (see #72). fx, this way, are run by 2+ conditions: -called from outside via passed deps; -called by change of internal dep;

Arguments against

1. Not sure if effects must have that much autonomy to run on their own. Usually their run is controlled by external runner, they're not supposed to be run by themselves, they're controlled entity, a part of larger autonomous run, in BEM methodology applied to FRP, they're element of functionality, not block, whereas aspect is block.

2. Same for aspects - not sure if that's appropriate for them to be run externally. Ideally they should rerun only on collection state changes, that this aspect is subscribed to, to make sure collection is not dirty.