Closed bit-app-3000 closed 3 weeks ago
@bit-app-3000 Can you please describe a little more where/what the issue is or rather what the expected behavior should be and what you feel is going wrong? I.e. a bit more context please... Sorry, I watched the video a few times, but can't really figure out what parts are wrong... Even better would be a codesandbox or upload the example somewhere so it can be debugged... thanks! :)
thanks for the response
expected behavior : function (component) is executed (dispatched) once unexpected behavior : the number of function (component) calls accumulates
I'm sorry, @bit-app-3000 — I've downloaded the video and went through it step by step, but without a working example or at least a little description of what you're doing I don't even know which part (or component) I'm supposed to focus on (I'm guessing the dropdown?). I'm a busy with lots of things, but I really do want to help — though, that also requires from you, as the person asking for help, to provide a bit more context/details, please... thank you! 👍
made an example
src: https://github.com/bit-app-3000/dummy
public: https://dummy-3xu.pages.dev
I hope it helps
Hey again — thank you for this, but again: Please describe and explain in a few sentences what I should be looking at here?
All I understand from the little (context) you provided so far is that some component is being unmounted/replaced multiple times (from the log messages it seems maybe the dropdown), but again if you cannot describe the problem a bit more, I unfortunately really don't know how I can help you... That example project of your has way too many files (most unrelated to the problem at hand) and from the title of this issue, I really just don't have enough information to understand what the actual problem is here... and it's not for a lack of trying!
Maybe I'm missing something obvious, so also grateful if anyone else would like to chip in here...
unexpected dispatch $replace after change route / reload layout
dispatch dropdown after change route executed more than once
maybe not unsubscribe correctly
you can see in the logs that the execution of the function is accumulating in this case a dropdown component
Hi @bit-app-3000 — so because your project has way too many files and I also couldn't get it to run locally, I still couldn't figure out what is going wrong in your case, but I've just created & uploaded a new example with a similar setup/task, i.e. a router & atom-based component switcher (incl. dynamic/reactive lists of images). I hope this much more stripped down example will help you figure out what might be wrong on your end, but I'm afraid that's all I can offer you here... obviously always happy to answer any other related questions
Demo: https://demo.thi.ng/umbrella/rdom-router/
Source: https://github.com/thi-ng/umbrella/blob/develop/examples/rdom-router/src/index.ts
Really hope that helps!
@bit-app-3000 I just updated the example with some more features and more comments (also requires a newer version of thi.ng/router, just published) :) Hth!
unexpected behavior occurs when using the component function signature (hiccup)
[fn, arg1, arg2, ...]
if you use the direct call in the tree it works as it should
[tag, {}, fn(args)]
Please add an example using such a signature
["tag", {...}, "body", 23, function, [...]]
[function, arg1, arg2, ...]
https://github.com/thi-ng/umbrella/tree/develop/packages/hiccup#what-is-hiccup
Those should be working like this:
const myComponent = (...items: any[]) => [
"div",
{ class: "custom" },
...items.map((x) => x.toUpperCase()).join(", "),
];
$compile([myComponent, "yabba", "dabba", "doo"]).mount(document.body);
Zero-arg functions in child/body positions... (only supported since rdom v1.5.0, released just now)
const random = () => ["li", {}, Math.floor(Math.random() * 100)];
$compile(["ul", {}, random, random, random]).mount(document.body);
Hi @postspectacular
made a minimal example with unexpected behavior of the component
import { defAtom } from '@thi.ng/atom'
import { ConsoleLogger, ROOT } from '@thi.ng/logger'
import { $compile, $replace, $switch } from '@thi.ng/rdom'
import { EVENT_ROUTE_CHANGED, HTMLRouter } from '@thi.ng/router'
import { fromView } from '@thi.ng/rstream'
import { cycle } from '@thi.ng/transducers'
ROOT.set(new ConsoleLogger())
const routes = [
{ id: 'home', match: ['home'] },
{ id: 'about', match: ['about'] },
{ id: 'profile', match: ['profile'] }
]
const router = new HTMLRouter({
routes,
default: 'home',
useFragment: true
})
const db = defAtom({
route: { id: 'home' },
x1: { state: false, label: '🤠' },
x2: { state: false, label: '☠️' }
})
// Pop Component
const emojis = cycle(['🥳', '🙂', '️😏', '😒', '🙂', '️😞', '😔', '😕', '🙁'])
const toggle = id => () =>
db.swapIn(id, last => ({
...last,
state: !last.state,
label: last.state ? emojis.next().value : last.label
}))
const slot = x => {
const { state, label } = x
return state
? ['emoji', {}, label]
: null
}
export const pop = (id, desc) =>
[
'pop', {},
['button', { onpointerdown: toggle(id) }, desc],
$replace(fromView(db, { path: id, tx: slot }))
]
// PageNav
const nav = () => [
'nav', {},
...routes.map(({ id }) => ['a', { href: router.format(id) }, id])
]
// PageContent
const container = (title, ...body) =>
[
'header', {}, nav(),
['main', {}, ['h1', {}, title], ...body]
]
const home = () =>
container(
'Home',
[
'div', {},
// component behavior
// expected
['p', {}, pop('x1', 'expected behavior')],
// unexpected
['p', {}, [pop, 'x2', 'unexpected behavior']]
]
)
const about = () => container('About', ['section', {}, 'About us'])
const profile = () => container('Profile', ['section', {}, 'Profile'])
router.addListener(EVENT_ROUTE_CHANGED, ({ value }) => db.resetIn('route', value))
router.start()
$compile(
$switch(
fromView(db, { path: ['route'] }),
({ id }) => id,
{ home, profile, about }
)).mount(document.getElementById('app'))
I hope for your help
You know, it'd be really good of you in the future to please actually describe what is the unexpected behavior you're observing. You keep on having me guess and spend a lot of time trying to figure out which parts are unexpected — it's not really helpful!
From what I could figure, it seems in some circumstances components containing the [fn, arg...]
form don't seem to properly unmount and hence when switching to another route and then back, the earlier non-cleared reactive fromView()
subscription is still active, plus a new one is being created and so on...
About these embedded function forms, in general:
[fn, arg1, arg2]
vs calling fn(arg1, arg2)
directly in rdom (or it can already be handled via other means).So two more questions for you:
Can you please explain WHY you're intending to use these forms? WHAT is your specific need of using this embedded form compared to using normal function calls?
Thanks
You know, it'd be really good of you in the future to please actually describe what is the unexpected behavior you're observing. You keep on having me guess and spend a lot of time trying to figure out which parts are unexpected — it's not really helpful!
From what I could figure, it seems in some circumstances components containing the
[fn, arg...]
form don't seem to properly unmount and hence when switching to another route and then back, the earlier non-cleared reactivefromView()
subscription is still active, plus a new one is being created and so on...About these embedded function forms, in general:
- Theyse forms are a legacy feature from the older thi.ng/hdom approach and are actually not that useful at all with rdom. I.e there's no real benefit of using
[fn, arg1, arg2]
vs callingfn(arg1, arg2)
directly in rdom (or it can already be handled via other means).- Because of the previous point, I've actually been tempted for a while to completely remove support for these forms in a future version of rdom. Their handling adds unnecessary complexity with no real gain (and obviously some edge cases are still not 100% right anyway)
So two more questions for you:
Can you please explain WHY you're intending to use these forms? WHAT is your specific need of using this embedded form compared to using normal function calls?
Thanks
@postspectacular plan to use in declarative design system components
// example.json
[
"page", {},
["HeaderLayout"],
"main", {},
[
"section", {},
[
"bar", {},
[
"PopOver", {
"id": "x1",
"state": "show",
"placement": "top-end",
"layout": ["Tooltip", "contentId"]
}
],
[
"PopOver", {
"id": "x2",
"placement": "top",
"layout": "Description"
}
],
[
"PopOver", {
"id": "x3",
"placement": "top",
"layout": ["h1", {}, "Tooltip"]
}
],
]
],
["FooterLayout"]
]
Lower Case: html tag Camel Case: component definition ( Only first array element )
@bit-app-3000 that's very helpful to learn & a great use case — thank you!
I've updated the $compile()
function to add checks for embedded function forms, call the function and then only compile the result... I'm doing some more testing and then release asap (your example above has no more problems now, as far as i can tell!)
thx works as it should!
Regards
https://github.com/thi-ng/umbrella/assets/42169423/d887122f-e34e-4555-b044-84a956a66144