-
Notifications
You must be signed in to change notification settings - Fork 219
Child component gets rendered outside of parent, being moved to bottom of HTML body #802
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
I think I had a similar issue to this, where I was rendering one of two slot components, based on some input to the parent component. Something like this: render :: State -> H.ComponentHTML Action ChildSlots m
render { loginType } =
case loginType of
Just (ULC.UL _) -> HH.slot (Proxy :: _ "passwordSlot") unit Pass.form
unit
HandlePass
Just (ULC.Cell cell) -> HH.slot (Proxy :: _ "verificationSlot") unit Ver.form
cell
HandleCode
Nothing -> HH.slot (Proxy :: _ "userloginOrCellSlot") unit ULC.form unit
HandleULOrCell which after some interactions and state changes in the parent, which caused the rendered child slot to switch, if I changed the route, (from login page to home page for example), the new page's HTML would be added to the document, but the child slot from the old page would not be removed. I solved it by wrapping the child slots inside a div like this: render { loginType } =
HH.div_
[ case loginType of
Just (ULC.UL _) -> HH.slot (Proxy :: _ "passwordSlot") unit Pass.form
unit
HandlePass
Just (ULC.Cell cell) -> HH.slot (Proxy :: _ "verificationSlot") unit
Ver.form
cell
HandleCode
Nothing -> HH.slot (Proxy :: _ "userloginOrCellSlot") unit ULC.form
unit
HandleULOrCell
] My guess is that when a component is to be removed from the document, halogen's diffing algorithm somehow looks for the root node of the component which is to be removed and since it has changed completely (not the same root when it was mounted), it can't find it and the child components remain in the DOM. So I suggest you wrap your rendered slots inside a div and see if it changes anything for you: render: \state -> HH.div_
[case state of
Left a -> html a
Right a -> slot _nil unit h a Raise] Not sure if my situation is the same as yours, but I think it's worth a try. Let me know if it works, because I'm not sure if my thinking is correct. If it is, I think it would count as a bug. |
It's definitely a bug! I thought I'd tagged this issue as such, or that possibly it's a duplicate of another actually, as I've definitely heard about this problem before (using a slot directly inside render causing problems). I think about it quite often, but haven't gotten around to dedicating some time to figuring out how exactly it's going wrong. |
It comes up somewhat often — for example, just a few days ago: (the halogen-store And perhaps it relates to this? |
Thanks for the links 👍, I knew it definitely happened in relation to |
I tried wrapping my render functions in a div like the workaround suggested, and it does seem like that fixed it. Thanks. |
I've been experiencing some bizarre non-deterministic behaviour in an app I'm writing, which I think might be a Halogen issue. Basically I've got a child component which occasionally somehow gets moved to the very bottom of the HTML body, outside of its parent. Unless my mental model of how components are supposed to work is completely wrong I can't see how this could ever happen in Halogen or in the code I've written, but trying to isolate the issue I think I've narrowed it down to a higher-order component I wrote like:
I'm wondering if there are any issues using higher-order components like this? I've used this combinator in a few places with no issues up until now, but it only started occurring once I introduced a new component that happens to be built using this; removing the call to
premap
seems to remove the bug. The call topremap
is nested inside another component which is also built using it, and introducing the child component detaches things starting from the first parent which also usespremap
, so I start up with something like this:And end up with
Because of the non-determinism it's hard to be sure that I've absolutely found the cause of the issue, but I can usually manually trigger the issue in less than a minute when the new component is wrapped in the call to
premap
, even if the call is justpremap (\_ -> HH.text "") pure
. I haven't managed to trigger it without it.I've even managed to detach the component, click around the app so that a new component gets rendered correctly inside the grandparent, then detach that one as well, ending up with multiple components being rendered outside of the grandparent. This is without using integers or anything for the keys to slots, just proxies, which I assumed was necessary for Halogen to manage state internally, so I should think they would all need to share state, but once they get detached they don't seem to.
I'm really perplexed by the behaviour in any case. Inspecting the html and looking at the render functions together makes me think what is occurring shouldn't be possible.
The text was updated successfully, but these errors were encountered: