Hiyas,
New to hyperapp, though I've tried to write my open React alternatives, so understand a good bit under the hood. However, I was playing around with it, building the simple Todo app with JSX embedded in the main app, and defining the pragma as "h", which works just fine with any regular node, it seems, but simple text children fail with:
app.js:83 Uncaught TypeError: Cannot read property 'length' of undefined
which is in the call to createNode, here:
for (var i = 0; i < vdom.children.length; i++) {
node.appendChild(createNode(vdom.children[i] = maybeVNode(vdom.children[i]), listener, isSvg));
}
Presumably because hyperapp seems to have a unique call to text() versus the normal h()?
I may continue to play around with, but just wondering if anyone's gotten hyperapp to work using JSX? Possibly also using esbuild (which does it's own JSX transpilation - I do not want to rely on webpack, babel, etc...).
FWIW, here is the esbuild script I'm using, or can run it command-line with the comment above here:
//"build": "esbuild src/index.tsx --bundle --jsx-factory=h --inject:src/lib/h.ts --outfile=build/app.js && cp src/index.html build/",
require('esbuild').build({
entryPoints: ['src/app.jsx'],
outfile: 'build/app.js',
bundle: true,
jsxFactory: "h",
plugins: [scssPlugin, copyPlugin],
})
.then(r => {console.log("Build succeeded.")})
.catch((e) => {
console.log("Error", e.message);
process.exit(1)
})
@rw3iss see this: https://github.com/jorgebucaran/hyperapp/issues/989#issuecomment-732165556
Different issue but same answer applies I think.
Esbuild is new to me but with that jsx supporting alternative h you should be able to use the same setup with no other changes.
To summarize some of the other comments in that issue: JSX isn’t as popular as it one was for hyperappers, and it isn’t a standard after all either. Hyperapp could shave off bytes and increase performance by going with a simpler h+text pair for writing views - and many prefer that anyway.
If you’re looking for a more readable alternative you might take a look at https://github.com/jorgebucaran/hyperapp/tree/main/pkg/html or my own https://github.com/zaceno/hyperlit
But if you really prefer jsx the above answer should work for you.
@rw3iss see this: #989 (comment)
Different issue but same answer applies I think.
It works! Many thanks!! Looking forward to trying this library out to simplify needs.
One thing I just noticed is... simple click handlers seems to require a return of the state passed to them. Is that intended/normal, or is there a way to not require that (not that it's a huge problem)?
For instance:
let doSomething = (state, e) => {
console.log("do something", state, e)
}
app({
init: {},
view: (props) =>
<div class="text">
Test
<button onclick={doSomething}>Click Me</button>
</div>
,
node: document.getElementById("app"),
})
This will error if I don't return 'state' from doSomething.
@rw3iss You are correct. That's fully intentional. Hyperapp is actually a lot different from react/preact which does surprise many. Rather it is more like Elm, but implemented in javascript. Heavy on the functional programming idea (without the type-system ofc).
In case you were expecting Hyperapp to be similar to react/preact, you might want to start with the tutorial to get a feel for how Hyperapp is different. (recently updated it so it works again, after a long period of being broken 😅 )
Either way, here's a short explanation about state & event handlers:
Hyperapp keeps all state in one single global store. When any state changes, the entire view gets recalculated and rerendered. How does the state change? By _dispatching_ an _action_. Sounds very similar to redux+react so far? Well, _unlike_ redux, actions are not objects that get pushed in to a reducer. Rather, actions are _functions_ which themselves define the state transformation as a simple function. E g:
```js
const SetMyNameAction = (currentState, name) => ({
...currentState,
myName: name
})
(Notice we must return a _new_ object for the state. We cannot mutate the currentState and return it because then hyperapp would not know that the state has changed –– it looks like it's the same object to hyperapp)
All well and good but how do we get such an action dispatched? The function for dispatching actions is kept (mostly) hidden within hyperapp and not directly callable. This is where the event handlers come in. When you bind an event handler in the virtual dom, hyperapp will bind a call to the actual DOM event, to dispatch the bound value as an action.
In other words: what you put in `onclick` should be a function that takes the current state and returns a new state. Moreover the second argument to the action (the `name` in above example) will be the DOM Event object so that you could get the value of an input field for example.
Your example app should probably look like this to be more "hyperappish":
```jsx
const DoSomething = (state, e) => {
console.log("doing something", state, e)
return {didSomething: true}
}
app({
init: {didSomething: false},
view: (state) =>
<div class="text">
Test
<span hidden={!state.didSomething}>Did a thing!</span>
<button onclick={DoSomething}>Click Me</button>
</div>
,
node: document.getElementById("app"),
})
Hope that helps explain things!
That makes sense, thank you for the explanation. I should probably read the manual ;-) ... mostly working with other libraries similar to this, was just wondering about that state approach. I'll read more and try to do some more impressive things tomorrow, getting late here. Thanks again! Nice little library!
@rw3iss You're welcome! 🍻
Don't feel bad for not having "read the manual". Honestly there is very little up to date information as version 2 is technically "still in beta" (moving target ... hard for docs & 3d party libs). It has become quite stable recently, though. The tutorial I linked above is a good start and the API Reference is complete afaik. Beyond that, the slack channel is a good place to get help.
And really, with Hyperapp there really isn't a whole lot to learn. There are just a few concepts that do a few well defined things. All the rest is on you and your skills with javascript (or whatever you use that compiles to javascript)
Good luck and have fun! (Late here too 😴 )
Cool, thanks mate, gnight 🙂