Replies: 4 comments
-
If we ever get proper tuples in JS then I would use those. Not sure if the polyfill would work for this. |
Beta Was this translation helpful? Give feedback.
-
Frankly, the example in the documentation isn't great, and we can avoid this problem by designing the subscription differently. Your subscription too. 💁♂️ app({
...,
subscriptions: (state) => [
connectToServer(ReactToCommand, {
username: state.username,
password: state.password,
}),
],
}) Keep in mind that custom subscriptions should be uncommon. The API exists first and foremost so that official packages can hook into Hyperapp. The problem is that they're being slowly developed and we have no choice but to resort to custom subscriptions right now. |
Beta Was this translation helpful? Give feedback.
-
To give a bigger example where I can't see how to redesign it - I'm trying to glue hyperapp to MQTT (a pub-sub protocol that works over websockets). My vision of an ideal API would look like: MQTTSubscription({
url: [
"ws://myserver.com/mqtt",
"ws://backupserver.com/mqtt",
],
topics: [
"one/thing/to/subscribe/to",
"another/thing/to/subscribe/to",
],
client_options: {... a bunch of parameters to be passed to the mqtt.Client() constructor ...},
onopen(state) {...},
onmessage(state, topic, message) {...},
onclose(state) {...},
}) Right now I've changed that to make it work by accepting username / password as top-level props, then calling Also how does this work with arrays, eg subscribing to multiple topics (where the list of topics would be variable, based on the app state)? Have a different subscription for each topic? (And in the documentation example, have a different |
Beta Was this translation helpful? Give feedback.
-
I don't know what would be the best way to approach something like that, but I'd have const MQTT = (treeOfProps) => [mqtt, flatten(treeOfProps)] Here's another thought. Export props constructors and have the subscription take several arguments, not just a single props object, which you'd then use like so: MQTT(
action,
auth(state.username, state.password, "auth-flag"),
client(state.foobar, state.barbaz),
options(hoge, fuga, hiya)
)
Without real tuples, we can't make array props work OOTB, but we can get creative until they become available. const options = (a, id = " ") => Array.isArray(a) ? a.join(id) : a.split(id) I can use this function to turn an array into a string back and forth. Unsophisticated, but works for this case: const subscriptions = (state) => [
MQTT({
url: options([
"ws://myserver.com/mqtt",
"ws://backupserver.com/mqtt"
]),
topics: options([
"one/thing/to/subscribe/to",
"another/thing/to/subscribe/to",
]),
}),
] The |
Beta Was this translation helpful? Give feedback.
-
Right now "a subscription will be restarted whenever its
props
change" - which is very useful, and intuitive on the surface level; but something I found very unintuitive is that when you say something like (quoting the example subscription from the documentation):then hyperapp considers the props to have "changed" every time, so the subscription is constantly being restarted. This is because we're using javascript's strict equality --
["w", "a", "s", "d"] != ["w", "a", "s", "d"]
-- the arrays have the same value, but they are not the same array. In this trivial example, the fix is simple but ugly:But in my real-world examples, the props aren't constant, they're more like:
The ideas I've had to make that work are both complicated and ugly:
return [sub, props]
withreturn [sub, {encoded: JSON.stringify(props)}]
, and then havesub
decodeprops
when it wants to use them (adds complexity inside the subscription, but is transparent to the end-user)auth: {username: ...}
withauth_username: ...
- I now have an explosion of parameters, and can't pass an object as-is to an underlying library. Also this doesn't work for arrays.ConnectToServer(props)
withConnectToServer(memoise(props))
. This keeps the complexity in one self-contained place, but it feels bad, and involves keeping a copy of every object ever passed into it just in case we see an object with the same values in the future (ie, memory leak)props
in mystate
, egstate = {username: ..., conn_props: {auth: {username: ...}}
, which involves duplicating the data which feels very un-maintainable.None of these seem great :( Is there a better way of dealing with this that I've not seen yet?
I end up wondering if
shouldRestart
should compare by value instead of strict equality?shouldRestart
more complicated :(shouldRestart
slower :(Beta Was this translation helpful? Give feedback.
All reactions