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

Support Render Props #88

Open
ezhlobo opened this issue Jan 21, 2019 · 5 comments
Open

Support Render Props #88

ezhlobo opened this issue Jan 21, 2019 · 5 comments

Comments

@ezhlobo
Copy link
Member

ezhlobo commented Jan 21, 2019

What is "Render Props"?

https://reactjs.org/docs/render-props.html

It's important to use this because Context API works via this approach. React is currently testing hooks, which will simplify the whole work with pug, but still we need to either have a good support of it or add information to the README.

How it works now

So now we support this way to use render props:

function render(item) {
  return pug`
    p= item
  `
}

const test = pug`
  Child
    ${item => pug`
      p item
    `}
    
  Prop(children=${item => pug`
    p item
  `})
  
  ExternalChild
    = render
    
  ExternalProp(children=render)
`

Check it out

How to improve?

I'm happy to know any crazy idea to make it more attractive in use.

@ForbesLindesay
Copy link
Member

I think the best bet might be some new syntax:

const test = pug`
  Child
    =>(item)
      p item
    
  Prop
    =>children(item)
      p item
     
  ExternalProp(children=render)

This would require a plugin the the parser and the lexer. N.B. not set on this syntax, just bike shedding.

@mostrecent
Copy link

mostrecent commented Jan 28, 2019

@ezhlobo, thanks for creating this issue. If we add this feature we have our JSX killer ;) However, I like @ForbesLindesay suggestion a lot, super clean and minimal. It feels just a bit unfamiliar because of the reverse order of => and (item) but I don't have a better suggestion yet.

Also one note in this context: react-router-dom differentiates with its Router component between component=, render= and actual children. So, basically render= does not equal giving Route children: https://reacttraining.com/react-router/core/api/Route/route-render-methods

So, we'd need a render prop syntax which works as a child but also inline as attribute value. Hope I was clear.

@ForbesLindesay
Copy link
Member

From my example:

const test = pug`
  Route
    =>render(routeProps)
      h1 Route Contents
`;

Would become:

const test = <Route render={(routeProps) => <h1>Route Contents</h1>} />

still not a huge fan of the syntax though.

@skotchpine
Copy link

skotchpine commented Apr 22, 2021

I'm pretty unhappy about that syntax, too...

For the sake of consistency, here's how I see the unsugared version:

const test = pug`
  Route(render=(routeProps)=>${pug`
    h1 Route Contents
  `})
`

@skotchpine
Copy link

skotchpine commented Apr 22, 2021

While we're considering parser & lexer plugins, we could add to the babel plugin to re-purpose the embedding syntax we already have: (adding place attribute to clarify attribute usage)

const test = pug`
  Route(place='top' render=(routeProps)=>#[
    h1 Route Contents
  ])
`

I especially am uncomfortable with this one:

const test = pug`
  Nav(place='top' #render({content})[
    h1= content
  ])
`

AKA:

const test = pug`
  Nav(
    place='top'
    #render({content})[
      h1= content
    ]
  )
`

We could introduce (BAD IDEA) escapes that stop further indentation to get the shorthand:

const test = pug`
  Nav \
    place='top'
    #render({content}) \
      h1= content
`

Starting to smell like coffeescript. I think we're just hitting the integration limits of template literals here.

As a completely alternative approach, what if we were to embed js in pug rather than this way around?

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