6 ms·
I read about it but it just did not click as V1 did. Also I will not rewrite old code just for sake of change and I want all system to be on same framework if p
by czechdeveloper 6y ago
I read about it but it just did not click as V1 did.
Also I will not rewrite old code just for sake of change and I want all system to be on same framework if possible.
I may actually do my own fork where only difference will be passing root state and root actions in addition to partial ones, which will fix great amount of issues I have.
- hellcow 6y agoAgreed. The lack of lifecycle events in v2 complicates things a great deal for seemingly no reason. Subscriptions and Events are similar enough that they could have become a single thing, instead of having two highly similar but not-quite-the-same things to grok. The tuple syntax it uses is very strange coming from v1. I wish I could call it a strict upgrade instead of saying "some things are worse, but other things are better."
- jorgebucaran 6y agoIt's my fault for not fully understanding the functional universe I was getting into when I first started working on Hyperapp. The latest Hyperapp is more strict, but it's all in good measure. Lifecycle events are impure, that's why they're no-good. I can tell you that Hyperapp is not for everyone. If you want to write pure, immutable, functional JavaScript and think hard about client side app architecture (unidirectional state management, controlled side effects, toggleable subscriptions), then you'll love it. I also suggest looking at Elm while you're at it. If you are looking for a more accommodating, meet-in-the-middle kind of approach where you can mix programming styles, you might be better served by, say, P/React.
- _old_dude_ 6y agoIf we talk about functional API, did you consider providing a push method, like with a Promise, to express the updating of an effect or a subscription ? (the function 'update' in the code below) app({ init: 0, view: state => h("div", {}, [ h("h1", {}, state), h("button", { onclick: (state, event, update) => { window.setTimeout(() => update(state => state - 1), 1000); } }, "subtract"), h("button", { onclick: state => state + 1 }, "add") ]), node: document.getElementById("app") })
- jorgebucaran 6y agoWe built it into the framework, if you happen to be familiar with Elm, this should make sense right away, but here's how you'd write something like that using Hyperapp: import { h, app } from "hyperapp" import { delay } from "@hyperapp/time" const Decrement = (state) => state - 1 app({ init: 0, view: (state) => h("div", {}, [ h("h1", {}, state), h("button", { onclick: (state/*, event*/) => [state, delay(100, Decrement)], }, "subtract" ), h("button", { onclick: (state) => state + 1 }, "add"), ]), node: document.getElementById("app"), }) See how you never actually called setTimeout as that would be a side effect. Instead, we have "controlled effects" in Hyperapp. This `delay` function doesn't even call setTimeout itself, but return an object that tells Hyperapp how. Just like how `h("button")` or `<button>` with JSX doesn't actually create a button, but an object representation of it. Finally this part: [state, delay(100, Decrement)], only placed here for convenience (as you'll usually want that in its own action) is how you tell Hyperapp to do the effect when the button is clicked. This is the same (model Cmd) continuation pattern used in Elm.
- _old_dude_ 6y agoI'm familiar with Elm but i think the model of Hyperapp is better than the [state command] pattern. This is how i see Hyperapp, the event part of Hyperapp is not about commands, it's about transition functions, functions that takes a before state and returns an after state. Hyperapp doesn't let the user to control the state by itself. But there is worst, the problem with the pattern [state command] is that it doesn't work well with async method, because at the time the command is called, the state which is passed alongside the command and the state maintained by Hyperapp may be different. With your example, the issue is that Decrement may be called on a previous state and not on the actual state. The idea of the updater is to provide the function that takes the transition function as parameter, so delay will be written that way function delay(updater, timeout, fun) { window.setTimeout(() => updater(fun), timeout); } If you want to decrement the state after a delay using the state at that time h("button", { onclick: (state, _, updater) => delay(updater, 100, Decrement), }, "subtract") (from the Hyperapp perspective, the event listener return undefined so you don't have to update the state at the time the event listener is called) and if you want to decrement the state using the state at the time the user click h("button", { onclick: (state, _, updater) => delay(updater, 100, _ => Decrement(state)), }, "subtract") The other benefit is that because delay() takes an updater as first argument, it's clear that the function delay does a side effect. Conceptually, the idea is that instead of trying to hide the side effect, you make it clear to the developer (more like Haskell does).