rawjs icon indicating copy to clipboard operation
rawjs copied to clipboard

Improvements to JSX

Open kbairak opened this issue 1 year ago • 1 comments

I have two proposals to improve JSX functionaity:

  1. Allow saving DOM elements to this. Lets use the word ref for this since it's the closest analogy to React. So this:
class Counter {
  constructor() {
    this.head = (
      <div>
        Count: <span ref="counterSpan">0</span>
        <button onClick={() => this.handleClick()}>Increment</button>
      </div>
    );
  }

  handleClick() {
    const prev = parseInt(this.counterSpan.textContent);
    this.counterSpan.textContent = `${prev + 1}`;
  }
}

Would be equivalent to this:

class Counter {
  constructor() {
    this.head = raw.div(
      raw.text('Count: '),
      this.counterSpan = raw.span(raw.text('0')),
      raw.button(raw.text('Increment', raw.on('click', () => this.handleClick()))),
    );
  }

  handleClick() {
    const prev = parseInt(this.counterSpan.textContent);
    this.counterSpan.textContent = `${prev + 1}`;
  }
}
  1. If the tag's name starts with a capital letter, use a class from the local scope that defines the head attribute. So this:
class App {
  constructor() {
    this.head = (
      <div>
        <h1>My awesome app</h1>
        <Counter />
      </div>
    );
  }
}

Would be equivalent to this:

class App {
  constructor() {
    this.head = raw.div(
      raw.h1(raw.text('My awesome app')),
      (new Counter()).head,
    );
  }
}

kbairak avatar Jan 30 '24 16:01 kbairak

I'm pretty sure you can already do the first one like this:

constructor() {
  this.head = <div>
    (this.counterSpan = <span>...</span>)
  </div>
}

As far as the second one goes, you're dealing with two different application scopes so I'm not sure how RawJS's raw.jsx function scope would be able to access the scope user space.

FWIW, the Raw.Param definition has built-in support for objects that have a .head whose type is HTMLElement, so you can shorten your second example to:

class App {
  constructor() {
    this.head = raw.div(
      raw.h1(raw.text('My awesome app')),
      new Counter(),
    );
  }
}

paul-go avatar Jan 30 '24 23:01 paul-go