wavesoft / dot-dom

.dom is a tiny (512 byte) template engine that uses virtual DOM and some of react principles
Apache License 2.0
806 stars 53 forks source link

Error with higher level components at depth #30

Closed SilentCicero closed 5 years ago

SilentCicero commented 7 years ago
import { H, R } from 'dot-dom';

function Page1() {
  return H('div');
}

function Page2() {
  return H(Page1);
}

R(
  H(Page2),
  document.body,
);

Throws this error:

Uncaught DOMException: Failed to execute 'createElement' on 'Document': The tag name provided ('function Page1() {
  return (0, _dotDom.H)('div');
}') is not a valid name.
    at http://localhost:3000/bundle.js:5425:51
    at Array.map (native)
    at render (http://localhost:3000/bundle.js:5374:38)
    at Object.<anonymous> (http://localhost:3000/bundle.js:4177:15)
    at __webpack_require__ (http://localhost:3000/bundle.js:21:30)
    at Object.defineProperty.value (http://localhost:3000/bundle.js:12114:18)
    at __webpack_require__ (http://localhost:3000/bundle.js:21:30)
    at module.exports.ctor.super_ (http://localhost:3000/bundle.js:67:18)
    at http://localhost:3000/bundle.js:70:10

Flagging this line first:

      ? document.createTextNode(vnode) : document.createElement(vnode.E);
SilentCicero commented 7 years ago

It seems that I have to nest them.. but why.

Valid:

import { H, R } from 'dot-dom';

function Page1() {
  return H('div');
}

function Page2() {
  return H('div', H(Page1));
}

R(
  H(Page2),
  document.body,
);

Not Valid:

import { H, R } from 'dot-dom';

function Page1() {
  return H('div');
}

function Page2() {
  return H(Page1);
}

R(
  H(Page2),
  document.body,
);
SilentCicero commented 7 years ago

My hack, dont know if this will screw the whole dom up though:

const o = (v) => (v.E && v.E.call ?            // If the vnode is a functional component, expand
          o(v.E(                                                    // it and replace the current vnode variable.

            v.P,                                                  // 1. The component properties
            _state[0],                                                // 2. The stateful component state
            (newState) =>                                             // 3. The setState function

              Object.assign(                                          // First we update the state part of the record
                _state[0],                                            // Note: When we defined the variable we kept the
                newState                                              //       reference to the record array
              ) &&

              render(                                                 // We then trigger the same render cycle that will
                vnodes,                                               // update the DOM
                dom,
                _npath
              )

          )) : v);

        vnode = o(vnode);
SilentCicero commented 7 years ago

@wavesoft any thoughts on this one? ^^

wavesoft commented 7 years ago

Oh, blast I didn't read this. Yeah I know what causes this 😞

This is caused by a size-vs-feature tradeoff and must definitely be mentioned in the Caveats. I saw you figured out that the functional component is evaluated only once here: https://github.com/wavesoft/dot-dom/blob/master/src/dotdom.js#L105

Therefore, the library "assumes" that it will receive some VNode as a response and not a nested component. That's why return H('div', H(SubComponent)) works and return H(SubComponent) doesn't.

A recursive approach as the one you suggested seems to be a good idea, but the problem is that a stateful component needs a rendered node on which to store the state record. The bottom line is that your solution works, but the first + child components will share the same state.

Though from the top of my I head I think doing something like _npath + '>' would fix that issue.

SilentCicero commented 7 years ago

@wavesoft something to be considered for sure. I'll try out the _npath + '>'. Are you sure this would fix the state issue? Is the state actually going to be different? Do you have an email I can reach you at? I dont really use linkedin. Yes, adding that to the path would seem to work in this case.

wavesoft commented 7 years ago

Hey @SilentCicero , I just created a gitter for the project, you can find me there 😄

SilentCicero commented 7 years ago

@wavesoft checkout the PR ;)

wavesoft commented 7 years ago

This is still not fully addressed so I am adding the bug label

wavesoft commented 5 years ago

This is now fixed on the latest 0.3.0 release 🎉