Skip to content

[rdom]: updating state inside a $replace that no longer has it's parent #410

@maxsei

Description

@maxsei

It seems that continuously updating the state of a $replace component that has a $replace inside of it causes the inner $replace to get into an invalid state because the parent no longer exists. Is this intended behavior and/or misuse of rdom, or can this problem be solved within rdom itself?

import { defAtom } from "@thi.ng/atom";
import * as rx from "@thi.ng/rstream";
import * as tx from "@thi.ng/transducers";
import { ComponentLike } from "@thi.ng/rdom";
import { $compile, $replace } from "@thi.ng/rdom";

const root = document.getElementById("root");
if (!(root instanceof HTMLElement)) throw new Error("Root element not found");

const modal = defAtom<ComponentLike[]>([]);
const modalContainer = (body?: ComponentLike) =>
  body && [
    "div.absolute.absolute--fill.justify-center.items-center.flex.dn",
    { style: { "pointer-events": "none" } },
    body,
  ];

const window_of_5_random_numbers = ()=>rx
  .fromInterval(1000)
  .transform(
    tx.comp(
      tx.map(() => parseFloat(Math.random().toFixed(3))),
      tx.slidingWindow(5),
      tx.map((xx) => ["div", {}, xx.join(", ")]),
    ),
  )
  .subscribe(rx.trace("window_of_5_random_numbers"));

const rdom = $compile([
  "div.relative.vh-100",
  {},
  $replace(
    rx
      .fromAtom(modal)
      .subscribe(rx.trace("modal"))
      .map((x) => x[0])
      .map(modalContainer),
  ),
  [
    "button",
    {
      onclick: () => {
        modal.swap((prev) => [...prev, $replace(window_of_5_random_numbers())]);
      },
    },
    "Click Me to Push Random Numbers into the Modal",
  ],
  [
    "button",
    {
      onclick: () => {
        modal.swap((prev) => {
          prev.shift();
          return [...prev];
        });
      },
    },
    "click me to pop modal",
  ],
]);
rdom.mount(root);

After clicking the "Click Me to Push Random Numbers into the Modal" twice in a row

Uncaught (in promise) TypeError: this.parent is undefined
    mount sub.js:27
    mount compile.js:74
    update replace.js:60
    next sub.js:39
    add scheduler.js:41
    next sub.js:39
    dispatchTo subscription.js:219
    dispatch subscription.js:233
    dispatchXformVals subscription.js:267
    dispatchXform subscription.js:247
    next subscription.js:163
    dispatchTo subscription.js:219
    dispatch subscription.js:233
    dispatchXformVals subscription.js:267
    dispatchXform subscription.js:247
    next subscription.js:163
    dispatchTo subscription.js:219
    dispatch subscription.js:233
    next subscription.js:163
    dispatchTo subscription.js:219
    dispatch subscription.js:233
    next subscription.js:163
    fromAtom atom.js:44
    notifyWatches iwatch.js:25
    reset atom.js:37
    swap atom.js:47
    onclick main.ts:43
    setAttrib dom.js:275
    $attribs dom.js:261
    $el dom.js:130
    $treeTag dom.js:76
    $treeElem dom.js:58
    $tree dom.js:44
    mount compile.js:96
    mount compile.js:74
    <anonymous> main.ts:61
sub.js:27:8

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions