Hyperapp: Nested Update/Effects

Created on 9 Feb 2017  路  18Comments  路  Source: jorgebucaran/hyperapp

Have you considered this:

app({
    update: {
        example: {
            attempt: () => alert(1)
        }
    }
})

It should then be possible to call msg.example.attempt().



Meanwhile I ended up using this

const convert = (actions, prefix = '') => Object
    .keys(actions)
    .map(name => typeof actions[name] === 'function'
        ? ({[`${prefix[0].toLowerCase()}${prefix.slice(1)}${name[0].toUpperCase()}${name.slice(1)}`]: actions[name]})
        : (convert(actions[name], `${prefix}${name[0].toUpperCase()}${name.slice(1)}`))
    )
    .reduce((a, b) => Object.assign(a, b), {})

app({
    update: convert({
        example: {
            attempt: () => alert(1)
        }
    })
})

This maps example.attempt to exampleAttempt.

Discussion

Most helpful comment

@selfup This is possible though:

app({
    update: {
        ...red,
        ...blue,
        ...yellow
    }
})

All 18 comments

@dodekeract Interesting. Nope. I never considered this.

Sometimes because it's nice to have doesn't mean we should have it, but I am open to feedback.

Don't see value. It is better to be flat. But any use case, more real examples?

@tunnckoCore basically anything with lots of updates/effects. That way it'd be possible to split it into multiple files. It's also less tedious to prevent name clashes and easier to remember the names.

@dodekeract

const red = require("./red-effects")
const blue = require("./blue-effects")
const yellow = require("./yellow-effects")

app({
  update: Object.assign({}, red, blue, yellow)
})

Does that make sense?

@jbucaran it makes, but there may be name collisions... That's the important thing.

choo solved this with namespaces IIRC.

I didn't like the idea of namespaces, so I didn't implement any.

What other options do we have?

choo solved this with namespaces IIRC.

Yes and no. Not exactly, or at least I think that they have the same problem in that case. There namespaces are for different models. Here we talk for one model.

@tunnckoCore We can talk about combining this with the solution for multiple models/components/etc. though.

Vuex (Vue.js equivalent to msg) also uses a flat structure. The reasoning is, as far as I understand it, that there is no practical benefit to namespacing/nesting over simply prefixing as a strategy to avoid naming collisions.

That said, I also am curious about strategies (in general -- not just for the reducers/effects) for structuring and sensibly managing larger scale, complex apps (with potentially hundreds of reducers). All my experience with really big and complex apps is from the world of MVC, and in coming to this brave new world of the Elm-ish/React-ish paradigm, I have mostly been exposed to trivial examples and haven't found much in terms of composing larger apps from smaller pieces (like a SAM equivalent of H(ierarchical)MVC for example).

@zaceno same here :) I was MVC a long ago, but still can get the Components thing really enough. But also don't have enough time and wish to review some big project using vue, react or whatever.

As about ELM-sh.. I really feel it easy and like it. Thanks to choo for very good README and intro to all that.

const red = require("./red-effects")
const blue = require("./blue-effects")
const yellow = require("./yellow-effects")

app({
  update: { red, blue, yellow }
})

Now there is no naming conflict but it is no longer flat 馃

@selfup This is possible though:

app({
    update: {
        ...red,
        ...blue,
        ...yellow
    }
})

@dodekeract Ohh that is nice too

But then i wonder what happens if the same keys are present...which one does it call?

@selfup the last one. In this case the one from yellow.

Oh interesting! Good to know there is a fallback

~Closing as I don't think I'll be implementing nested actions.~

I ended up using the same nested interface in my project also to compose components, seems pretty good so far.

Forgot to close here. This has been implemented by @dodekeract and it's available from 0.6.0 馃帀!

Now, reducers and effects, can be used as usual or instead of a single object with functions, can also have arbitrarily nested objects with more functions. These functions can be on the same level as the namespace or above, or under. It's recursive in nature, so you can go crazy with this.

The object that holds all this data,actions is initialized only once, so there is no fear of this slowing us down, in fact, after this HyperApp became faster. From 1.40 down to 1.37.

See #75.

/cc @nichoth

Was this page helpful?
0 / 5 - 0 ratings

Related issues

zhaotoday picture zhaotoday  路  3Comments

icylace picture icylace  路  3Comments

jscriptcoder picture jscriptcoder  路  4Comments

SkaterDad picture SkaterDad  路  3Comments

dwknippers picture dwknippers  路  3Comments