Skip to content
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

Using JSX with Bel #56

Open
arturi opened this issue Oct 23, 2016 · 10 comments
Open

Using JSX with Bel #56

arturi opened this issue Oct 23, 2016 · 10 comments

Comments

@arturi
Copy link

arturi commented Oct 23, 2016

I was wondering if its possible to use JSX instead of hyperx to create elements with Bel. I like to use Bel and Yo-yo, but sometimes its convenient to go JSX route, because then components could be re-used between Yo-yo/Choo and React projects.

I tried to set jsx pragma to h and then use it like so:

var h = require('bel').createElement

var el = <h1 class="a">Hi</h1>
document.body.appendChild(el)

But children (Hi) never appear, and if you omit class, bel complaints: Cannot read property 'namespace' of null. Got confused, probably missing something.

@nichoth
Copy link

nichoth commented Oct 23, 2016

Sometimes I have wished that all the h modules were more interoperable. They all have slight differences that make them incompatible. bel, virtual-hyperscript, hyperscript, and react all have slight differences, though they do basically the same thing.

@shama
Copy link
Member

shama commented Oct 23, 2016

What does the compiled JSX code look like?

@arturi
Copy link
Author

arturi commented Oct 23, 2016

Compiled JSX with createElement as pragma looks like this:

const el = createElement(
  'h1',
  null,
  'Hi!'
)

And Bel, according to the docs, expects it to be:

var sameElement = createElement('h1', { className: 'heading' }, ['Hi!'])

More complex nested example:

const el = <div>
  <h1>Hi, <strong>stranger</strong></h1>
  <h2>Hello</h2>
</div>

Transpiled:

const el = createElement(
  'div',
  null,
  createElement(
    'h1',
    null,
    'Hi, ',
    createElement(
      'strong',
      null,
      'stranger'
    )
  ),
  createElement(
    'h2',
    null,
    'Hello'
  )
);

@shama
Copy link
Member

shama commented Oct 23, 2016

So their spec expects createElement(tag, attrs, ...children)? I'm +1 on support their spec but low priority on my list.

@arturi
Copy link
Author

arturi commented Oct 23, 2016

So you’d want to support both or switch to their?

@shama
Copy link
Member

shama commented Oct 23, 2016

Support both if possible, not switch to theirs.

@yoshuawuyts
Copy link
Member

Hmmm, I feel the solution for bel / react compat would probably be to create
a form of generic adapter that allows for arbitrary nodes to be passed into
react, and
just work™ - similar to how we've done it with cache-element/widget but for
React

Does that make sense?

On Sun, Oct 23, 2016 at 5:25 AM nichoth notifications@github.com wrote:

Sometimes I have wished that all the h modules were more interoperable.
They all have slight differences that make them incompatible. bel,
virtual-hyperscript, hyperscript, and react all have slight differences,
though they do basically the same thing.


You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
#56 (comment), or mute
the thread
https://github.com/notifications/unsubscribe-auth/ACWlel4YFRXU1W3zFpjh5QOPGtl_69-hks5q2tOZgaJpZM4KeCR3
.

@yoshuawuyts
Copy link
Member

seems it took a while for my emails to arrive 😅

On Tue, Oct 25, 2016 at 8:42 PM Yoshua Wuyts notifications@github.com
wrote:

Hmmm, I feel the solution for bel / react compat would probably be to
create
a form of generic adapter that allows for arbitrary nodes to be passed into
react, and
just work™ - similar to how we've done it with cache-element/widget but for
React

Does that make sense?

On Sun, Oct 23, 2016 at 5:25 AM nichoth notifications@github.com wrote:

Sometimes I have wished that all the h modules were more interoperable.
They all have slight differences that make them incompatible. bel,
virtual-hyperscript, hyperscript, and react all have slight differences,
though they do basically the same thing.


You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
#56 (comment), or mute
the thread
<
https://github.com/notifications/unsubscribe-auth/ACWlel4YFRXU1W3zFpjh5QOPGtl_69-hks5q2tOZgaJpZM4KeCR3

.


You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
#56 (comment), or mute
the thread
https://github.com/notifications/unsubscribe-auth/ACWlehKji7daqf9h4aF59xpz913D_jmhks5q3k16gaJpZM4KeCR3
.

@tunnckoCore
Copy link

One more thing related to this "spec" compliance is because to support components, not tags which means passing a functions as first argument not a string

var el = <Link foo="bar">Hello</Link>

is transpiled to

// should also support content to be a string, not an array
// because currently isn't possible
var el = createElement(Link, { foo: 'bar' }, ['Hello'])

@tunnckoCore
Copy link

tunnckoCore commented Apr 19, 2017

kinda such thing

function arrayify (val) {
  if (!val) return [];
  if (Array.isArray(val)) return val;
  return [val];
}

function isObject (val) {
  return val && typeof val === 'object' && !Array.isArray(val)
}

function belCreateElement (tag, props, children) {
  var el

  children = arrayify(children)
  props = isObject(props) ? props : {}

  if (typeof tag === 'function') {
    // not sure for the order
    // but we should have `children` on `props` object
    props.children = children || arrayify(props.children)
    var _ele = tag(props, props.children)
    
    // should remove `_ele._attributes.null.children`
    return _ele
  }

  // not changed code below ...
}

seems to be working

examples

function Link (props) {
  return belCreateElement('a', props, props.children.concat(' world!!'))
}

var el = belCreateElement(Link, { className: 'foo' }, 'Hello')

console.log(el.toString())

Ahref, not using props argument directly (important to test both above and below cases!)

function Ahref ({ className, children }) {
  return belCreateElement('a', { className }, children.concat(' world!!'))
}

var el = belCreateElement(Ahref, { className: 'foo' }, 'Hello')

console.log(el.toString())

MOAR

var hx = require('hyperx')(belCreateElement)

function Link (props) {
  // JSX
  // <a { ...props }>{ props.children.concat(' world...').join('') }</a>
  return hx`<a ${ /* ...props */ } >${ props.children.concat(' world...').join('') }</a>`
}

// JSX
// var el = <Link className="foobar">Hello</Link>
var el = belCreateElement(Link, { className: 'foobar' }, 'Hello')

console.log(el.toString())
// expected
// => '<a class="foobar">Hello world...</a>'

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants