Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Nesting Specs #54

Open
spencerjanssen opened this issue Jan 29, 2016 · 8 comments
Open

Nesting Specs #54

spencerjanssen opened this issue Jan 29, 2016 · 8 comments

Comments

@spencerjanssen
Copy link
Contributor

Thermite has the concept of sequencing Specs via the Semigroup instance, but sometimes you want to nest the markup of a Spec inside another. Lately I've been using this helper function:

wrap :: forall eff state props action.
    Spec eff state props action ->
    Spec eff state props action ->
    Spec eff state props action
wrap parent child = simpleSpec pa rn 
 where
    pa a p st k = do
        view _performAction parent a p st k
        view _performAction child a p st k
    rn k p st children = view _render parent k p st (view _render child k p st children)

At this point, I'm not sure whether this re-appropriation of the children argument is elegant or hacky. Does it make sense to add a function like this to Thermite? I'm definitely open to better names as well.

@paf31
Copy link
Owner

paf31 commented Jan 29, 2016

Hmm, that's interesting. I expected users would pass a Spec for any inner component as a function argument, but I suppose it makes sense to use the children property instead. I suppose it is a little hacky, but then that argument has always been undocumented, so we can call this the default going forward, and document that any React-provided children will be passed in at the top level.

I think the name wrap might be used though.

@paf31
Copy link
Owner

paf31 commented Jan 29, 2016

Another question is: should the children be passed as a singleton array? Or even pass an array of child Specs?

@pkamenarsky
Copy link

This is what I came up with:

render dispatch _ state _ = 
   [ R.div [...] [ view T._render childSpec dispatch {} state [] ]

childSpec can of course be focused to use some substate/action. Is there a more idiomatic way to do that?

Furthermore, what would props be used for in Thermite? When using focused specs there's only one global state anyway, or am I missing something?

@pkamenarsky
Copy link

I'm not sure how useful that would be, but if Render was a Reader monad, it would be possible to pass down dispatch/state to child specs implicitly.

@paf31
Copy link
Owner

paf31 commented Feb 3, 2016

@pkamenarsky I think focusing would use a separate call to focusState etc.

Props are used at the top-level when the full component is integrated into a larger React application.

I'm interested in the Reader approach, for sure, but it adds a cognitive overhead for new users which I'd like to avoid. Right now, all you need to get started is functions and data types (I consider the lens stuff to be an advanced feature, but even then, you don't need to know about type classes or monads to use it).

@pkamenarsky
Copy link

@paf31 Yes, focusing is a separate call (i.e. childSpec = focus ...). What I meant though is that it would be cool to be able to nest components the same way other elements are nested:

[ R.div [...] [ chidComponent [...] [...] ]

without having to call render explicitly. But I guess that would only be possible with the Reader approach - and I agree, the mental overhead probably doesn't justify that.

re props - so if the whole application is written in Thermite, props are basically useless?

@paf31
Copy link
Owner

paf31 commented Feb 3, 2016

Pretty much, on the props thing.

@teh
Copy link

teh commented Sep 20, 2016

I have an almost identical function

nestSpec :: forall eff state props action. T.Spec eff state props action -> T.Spec eff state props action -> T.Spec eff state props action
nestSpec parent child = T.simpleSpec performAction render
 where
   performAction a p st = do
     view T._performAction parent a p st
     view T._performAction child a p st
   render k p st children = view T._render parent k p st (view T._render child k p st children)

Would you be open for a PR?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants