Comments (9)
(getting dejavus with implementing jquery-spect, exactly the thing.)
Seems that we're limited in hooks to repeat react. There's no known for me way for out-of-scope function to detect the scope (in general case) it was called from, so the effects are quite limited in use-cases, quite like react.
Switching state manually isn't useful for async calls either.
Seems that we're off with jquery-spect only, providing aspect builder plugin, and pure no-jquery version.
from spect.
jQuery code is confusing and noisy, although promising for jquery land: https://gist.github.com/dy/a556d817042c3d492455e93831fd3572.
Within all options, scope detection is the fastest and the safest.
We can hoist up looking for the first matching effect, to avoid fn.toString
.
Static transform would provide robust solution.
from spect.
Ugh. That doesn't seem to be possible via stacktrace.
let log = [],
el = document.createElement('div'),
el2 = document.createElement('div')
// invocation site - available from stack
$(el, aspect)
// the definition site (start of aspect) - unavailable from stack
function aspect(el) {
log.push(state().x)
$(el2, el2 => {});
(
() => {
$(el2, el2 => {});
setTimeout(() => {
$(el2, el2 => {});
// the timeout site (topmost detectable)
(() => state({ x: 1 }))()
})
}
)()
}
Neither creating new function helps detecting aspect - we can get only site of function evaluator, which says nothing about exact aspect.
The new functions know nothing about imported deps, they need providing effects as arguments anyways.
So we're off with runtime sandboxing only via passing fx as args.
from spect.
Ok. Even if we try to create scoped function via scoped-function, we lose function surroundings, like imported modules. To use scoped functions, we have to indicate scope.
So seems that's proven - there's no way to provide context-less global effects directly, not changing their API (useState
-like, creating local reference) or keeping reference (jQuery).
from spect.
Afterthought
We could use state from timeout
effect as
function app(el) {
timeout(() => {
state()
})
}
In this case timeout
would enable aspect before triggering callback.
There's limitation for fx though:
function app(el) {
fx(async fn() {
await smth()
state()
})
}
The async tick is guaranteed, and for state
there's no way to identify target.
Why doubts in jQuery approach?
- Because
fx
can be a direct effect, there's no necessity to keep it attached to holder. - Because
route
must be a global effect, there's no sense to keep it per-element. - Because
html
is first-class anonymoushtml
constructor.
We could, actually, attach effects explicitly via deps, so that we wouldn't have to register implicit observables via reading some external state.
function app(el) {
fx(async (state, attr, id) => {
await tick()
// state is attached to current element context
state({ el: value})
}, state, attr, id)
}
That looks weird though - passing context along with attribs.
On the other side
- Domain connectors
$el.html = code
look way more natural - They can act as holders of effects, not necessary to create global imports.
from spect.
Although - state seems to be the only bottleneck.
If we redesign it as
let state = useState(defaults)
//...
setTimeout(()=>{
state.x = 1
})
from spect.
Getting back to this lovely approach.
jQuery-refs way has a set of disadvantages, most of all, confusing VDOM construction and $ mess: #80+.
If we actually provide all possible async effects #66 (comment), #67, we can go on with this approach. Global effects are valuable piece.
The only issue remains then - how to apply context.
use.call(target, el => {
state.id = 1
fx(() => {
attr(a => a.loading = true)(el)
attr.loading = true
state.user = await ky.get`./api/user/${ state('id') }`
attr.loading = false
}, [id])
html`<p use=${i18n}>${
attr.loading ? `Hello, ${ state.user.name }!` : `Thanks for patience...`
}</p>`
use(() => {
// like that probably?
// but how do we switch context back? eg. read initial state?
// mb contexts are not for that? eg. use(anotherAspect)
// or manual indeed? ctxStart(), ctxEnd()?
}, externalEl)
css`...`
})
Although even getContext('2d')
is basically an extension of element functionality. In other words we do
let elCtx = el.getContext('spect')
// or
let $el = context(el)
// or
let $el = spect(el)
So we just build a platform of contexts.
from spect.
Couple more reasons against jquery-refs. Yes, we add chaining, but.
- we have to create multiple wrappers.
- we can't easily store global state for example.
- we can't easily wrap any target
- it creates collection/single instance confusion
- having
effect(target, params)
would be just natural atomic pattern, allowing to wrap anything - having
effect(target)
would enable FP style naturally - there's still conflict importing global effects vs getting them via local instance
- there's conflict with real jQuery
- for every effect in jquery we anyways call
$target.fx(params)
- not much effort is saved vsfx(target, params)
- but the whole concept of wrappers is introduced, instead of centralized handling elements/collections without external stuff - spect wrapper is unfortunately ugly-ish in console
- direct effects resolves issue of components
html(target, h`${ data.map(tpl) }`)
const tpl = data => h`...`
html(target, h`${ data.map(item => h`<${Comp} ...${item}/>`) }`)
const comp = el => html(el)`<${}/>`
- that is lovely and natural to
change(target, how)
from spect.
Ok, that's a separate ticket.
from spect.
Related Issues (20)
- h: cache element by stack instead of creating anew HOT 1
- h: drop parser, use htm HOT 2
- v β f, v. Shaving off API, v as proxy HOT 6
- operators HOT 1
- 0b HOT 1
- v ~~as proxy~~ as observable HOT 1
- v: access multiarg values as [0], [1] etc. HOT 1
- $ β selector-collection HOT 2
- h: keyed. Why not morphing? HOT 3
- v(v0, v1, v2) - observables as args HOT 1
- $: pseudos? HOT 1
- h/$ - a nice way to convert data to template? HOT 2
- add Github Corner to spect.ly and fix typo HOT 2
- v23: animevents-only $ HOT 1
- 23.0: API reconsiderations, half-a-year later
- $: stop infinite recursion HOT 1
- $: first run flickers
- $(parent, β> childβ)
- h: lists; diff algo is underused. Possible syntax HOT 1
- spect@24 breaks integration tests with subscribable-things HOT 5
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
π Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. πππ
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google β€οΈ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from spect.