AlexGilleran / jsx-control-statements

Neater If and For for React JSX
https://www.npmjs.com/package/babel-plugin-jsx-control-statements
MIT License
1.62k stars 64 forks source link

Feature request: Render-prop transformation. #74

Open colshacol opened 6 years ago

colshacol commented 6 years ago

Currently, jsx-control-statements has <With>, and it is great and all (I've never used it 😆), but I believe the purpose of this tool is to help developers clean up their JSX, and it is mostly used with React.

Lately in React, render-props have taken the world by storm, especially with React about to drop the new Context API in only a few days.

example usage:

1_xhcieuad1g1rpv0c8myzva

I feel as though the hideousness of render-props would be a fantastic thing for jsx-control-statements to mask.

Here's an example of what will become more of a common pattern:

jjj

And here is what could be: (Mind you, the concept is in alpha!)

skdaksdka

The deviation is not that great, no. But it is still more aesthetically pleasing, and both of these samples were run through prettier, so they represent what would be almost globally accepted. Note that prettier wouldn't allow the destructuring to live on a single line because it is quite opinionated of object-like syntax in function declarations, but less-so inside props.

💪

AlexGilleran commented 6 years ago

That's really interesting! I'm definitely be open to including it although I don't have a lot of time to work on JSX Control Statements right now myself :).

AlexGilleran commented 6 years ago

Sorry about the slow response by the way, been procrastinating while I moved house and didn't realise this had gotten to 2 weeks.

colshacol commented 6 years ago

It is all good, friend. I forgot that I created this > a month ago!

I'll do some toying and see if I can get it working as a POC. :+1:

texttechne commented 6 years ago

I don't think this will work. With args={{store0, store1, store2}} you're actually creating a new object with the known variables store0, etc. which you then pass into the component <RenderFunc>. This is quite different than the first example where you destructure the first method parameter.

To put it differently, i.e. into code without destructuring:

<Observer inject={(stores) => ({ store0, store1, store2 })}>
  <RenderFunc args={stores}>{/* fails => where does this magical variable come from??? */}
    <div>{stores.store0}</div> 
  </RenderFunc>
</Observer>

The only solution I can actually conceive of is analogous to the way the <For> statement works:

<Observer inject={(stores) => ({ store0, store1, store2 })}>
  <RenderFunc args="stores">{/* just a string */}
    <div>{stores.store0}</div>  {/* look Ma, I'm a variable now! */}
  </RenderFunc>
</Observer>

Of course, this won't work with static typing.