Hyperapp: Nested actions and sliced state

Created on 3 Nov 2017  路  10Comments  路  Source: jorgebucaran/hyperapp

Heya! Sliced state concept is pretty fantastic by idea and is pretty unique to HyperApp, i believe. But.

There's one tricky and big BUT. Consider such example

app({
  state: {
    title: 'abc',
    foo: {
      hello: 'world',
      todo: {
        list: [],
        count: 0,
        done: 0,
      },
      bar: {
        xxx: 'xxx',
        baz: {
          zzz: 'zzz',
          qux: {
            hi: 'buddy',
            aa: 'bb',
          },
        },
      },
    },
  },
  actions: {
    // full state: state.title, state.foo, state.foo.hello and etc
    zazy: ({ state }) => {},
    foo: {
      // state.todo only
      todo: ({ state, actions }) => () => ({ count: state.list.length + 1 }),

      // state.bar only
      bar: {
        // access to: state.zzz & state.qux
        baz: ({ state, actions }) => () => ({ zzz: state.zzz + 'yyy' }),
      },
    },
  },
});

It turns out that when you have nested action named the same as some key in the state, then you partially are not able to access to upper state? Notice the foo - action and state. In the foo action we have two nested actions which want to deal with slice state separately, but because foo is object of actions then we can't get state.foo.hello for example. The only way that i see to access state.title and/or state.foo.hello is to create another "top-level" action which in turn can be access them and change them if that action is reducer (returning function).

It _may_ be confusing, but this concept is pretty powerful and super awesome! Congrats.

By the way, did you realize that you can pass return of an app() call directly to an action, haha? :rofl:

app({
  state: {
    hello: 'world',
    todo: {
      list: [],
      count: 0,
      done: 0,
    },
  },
  actions: {
    // state.hello & state.todo
    foo: (state, actions) => {},
    todo: app({
      actions: {
        // state.list, state.count & state.done
        add: (state, actions) => {},
        del: (state, actions) => {},
        list: (state, actions) => {},
      },
    }),
  },
});

btw, not sure if that work :D because probably app not works without state? May be kinda kool too :)

Docs Inquiry

All 10 comments

Hehe that's interesting. But nah, probably won't work as expected. Esp if your actions use the third argument. Also: why?! 馃槅

@olstenlarck I don't understand the issue. Actions are only able to access the slice of state under the same namespace. So, you can't access state.title inside actions.foo.bar, but you can inside actions.foo. This is by design.

@JorgeBucaran if I'm not mistaken he's asking the question everyone asks when first presented with sliced state/nested actions: but how do I get access to parent state? How do I call parent actions? Or sibling state/actions?

And @olstenlarck the answer is: don't. Structure your app so actions don't need access to parent state.

If you need to do a "combo" action of calling actions.A.foo when evever actions.B.bar(x) is called but only if x === 'baz', then compose that logic in a function, which you pass to your component event handlers (rather than just the actions.B.bar)

Gotcha. @olstenlarck What @zaceno said! 馃憢馃槃

It isn't really an issue. Initially it was named "am i understanding * correctly?". Just playing with the things that i thought from the first time when i seen that concept introduced. So, yea, i understanding it correctly and i will just need to add NON-matching-to-state-key to actions.foo like

app({
  // ...
  actions: {
    foo: {
      someKey: (state, actions) => {} // to access `state.foo`
    }
  }
})

@zaceno haha, good comment. Yea i got it immediately when seen it for the first time. My "problem"(actually was not so clear in my mind) how can get the state of actions.foo when i also want to have nested action in it for accessing and modifying nested state ;d But while writing the snippets i reallized how :D

But yea, after playing with cup of coffee and starting the issue it was clarified :D

@zaceno: if I'm not mistaken he's asking the question everyone asks when first presented with sliced state/nested actions: but how do I get access to parent state? How do I call parent actions? Or sibling state/actions?

It's pretty fantastic concept and i very like it. We can follow the discussion for it? some links would be good (i have more coffee to drink ;d)

@olstenlarck Not so many discussions really. That example I gave came out of a discussion on slack between me & @JorgeBucaran where I was arguing for the value of an event bus as a solution to the problem (which hyperapp used to have but recently took out), while Jorge was arguing for the aforementioned solution.

I think Jorge's approach is the right one for most cases, but I still believe there are situations where an event bus helps keep things nice and separate. If you're curious about that you could look into https://github.com/zaceno/hyperapp-events

Yea, i always like the event bus model. In most cases it simplifies the things a lot and makes (the app/framework) codebase a lot better and more maintainable.

Q1:

Btw, is it expected the nested action's actions param to not include (NOT access) the upper actions? hm.

Q2:

@zaceno: Structure your app so actions don't need access to parent state.

that's okey, i'm not curious about that, but exactly the opposite - does parent actions know that some children actions updated the state? and if not, why?

Hm ;d i definitely should open and play directly with latest version

I can try to answer the questions:

Q1: Yes. Both the state and actions are sliced.
Q2: The architecture is top-down, so parent鈫抍hild communication is the norm, and yes, "parent actions know that children actions update the state".

and actions are sliced.

Hm. Oookey, interesting.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

jorgebucaran picture jorgebucaran  路  3Comments

rbiggs picture rbiggs  路  4Comments

icylace picture icylace  路  3Comments

joshuahiggins picture joshuahiggins  路  4Comments

jacobtipp picture jacobtipp  路  3Comments