←back to thread

224 points vanviegen | 1 comments | | HN request time: 0.207s | source

Yes, another reactive UI framework for JavaScript. Bear with me, please... :-)

I 'invented' the concept for this back in 2011, and it was used (as a proprietary lib) in various startups. Even though many similar open source libs have been released since, and boy have I tried a lot of them, none have been able to capture the elegance and DX of what we had back then. I might be biased though. :-)

So I started creating a cleaned-up, modern, TypeScript, open source implementation for the concept about five years ago. After many iterations, working on the project on and off, I'm finally happy with its API and the developer experience it offers. I'm calling it 1.0!

The concept: It uses many small, anonymous functions for emitting DOM elements, and automatically reruns them when their underlying proxied data changes. This proxied data can be anything from simple values to complex, typed, and deeply nested data structures.

As I'm currently free to spend my time on labors of love like this, I'm planning to expand the ecosystem around this to include synchronizing data with a remote server/database, and to make CRUD apps very rapid and perhaps even pleasurable to implement.

I've celebrated 1.0 by creating a tutorial with editable interactive examples! https://aberdeenjs.org/Tutorial/

I would love to hear your feedback. The first few people to actually give Aberdeen a shot can expect fanatical support from me! :-)

Show context
catlifeonmars ◴[] No.43936868[source]
Why not JSX? There’s no real cost to making the API JSX compatible, from what I can tell, and tsc has builtin support for transpiling JSX. It would also make porting code a lot easier. I’m only saying this because the type signature of $ is so similar to createElement.

As an aside, I really like the class name and text content ergonomics (e.g div.someclass, span:some content). Reminiscent of pug/jade

replies(3): >>43937210 #>>43937389 #>>43937465 #
vanviegen ◴[] No.43937210[source]
I don't particularly like how control logic needs to be embedded within JSX using ?ternary : operators and .map(() => stuff) within the HTML.

Also, in order to transform JSX into individual rerunnable functions, we'd need a whole different transpiler. I like being able to code browser-runnable JavaScript directly.

To each their own. :-)

replies(5): >>43937239 #>>43937991 #>>43938712 #>>43939757 #>>43941298 #
WorldMaker ◴[] No.43937991[source]
> Also, in order to transform JSX into individual rerunnable functions, we'd need a whole different transpiler.

I don't think you would. `<Component prop="example" />` gets converted by current transpilers into `jsx(Component, { prop: "example" })`. The `Component` itself is passed as is. In the case of Components that are just functions, that passes the function as-is, as a function you can just call as needed.

JSX was built for "rerunnable functions". It's a lot of how React works under the hood.

replies(1): >>43938253 #
vanviegen ◴[] No.43938253[source]
The problem is that JSX transpilers will put child nodes in an array, instead of in an anonymous function, meaning there is no easy way (without transpiler magic) to rerender just a part of the component.

This JSX:

  <section><h1>Welcome</h1>{data.enabled ? <input /> : "disabled"}</section>
Which becomes this with Babel:

  _jsx("section", {children: [
    _jsx("h1", {children: "Welcome"}),
    data.enabled ? _jsx("input", {}) : "disabled"
  ]})
But we'd need something like this to fit Aberdeen:

  _jsx("section", ()=>{
    _jsx("h1", ()=>{_jsx("Welcome");});
    if (data.enabled) _jsx("input", {}) else _jsx("disabled");
  }})
In React you can, with some effort, limit virtual DOM rerenders to a single component. Aberdeen rerenders fractions of components by default, if that's all that needs to happen. That's why it works well operating directly on the actual DOM, without a virtual DOM inbetween.
replies(2): >>43938452 #>>43938692 #
ibash ◴[] No.43938692[source]
Modern react developers forget that if statements exist. When react was class based it was trivial to do:

  render() {
    if (this.dontNeedToRender) {
      return null
    }
  }
Now, because hooks can't be skipped, react developers jump through many hoops to use an if statement during rendering.
replies(1): >>43940319 #
1. prothy ◴[] No.43940319[source]
I might be missing your point, can you elaborate? If you want to write an if statement you just do it at the end of a component, after the hooks. It's a common pattern.