-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Proposal: compose several nested render-props components into a single one #600
Comments
@gnapse you may take a look on https://github.com/neoziro/recompact, it's doing something like transducer for components |
@pokorson nice! Did not know about that library. Still, on a quick glance I did not see something providing what I describe above. Can you point directly to it if it's somewhere in there? However, independently I found out about react-powerplug, which does provide something a-like, but I suspect it's intended to be used with the set of render props components that that library provides, and it's not suitable for general use. I'll check further. Still I think this library should provide something like that on its own. I already use it extensively, and some other projects do, so jumping to recompact just for the flattening of the tree and for being a drop-in replacement of this, is not always feasable. |
there was some discussion about this previously, you can check it here: and |
Again, I can't see the relevance on insisting on |
also could you post some example how would you expect it to look with hoc's instead of render props? |
As I said, I don't see that past issue #182 as being the same as what I'm proposing here. As a hoc it could look like this: const CounterWithTimer = composed(Counter, <Timer interval={1000} />);
<CounterWithTimer>
{(counterProps, timerProps) => ( ... )}
</CounterWithTimer> The above being used as a render prop could look like this: <Composed components={Counter, <Timer interval={1000} />}>
{(counterProps, timerProps) => ( ... )}
</Composed> |
I'm still referencing to this:
The way it can work is explained in first comment. And you're mixing these two concepts (hocs and render props). hoc is a function that return component. You should do composition on hoc's not components.
I think there's no way of passing props to your component from 2 different components except of nesting everything.
|
I'm not sure what you mean is not possible to pass to my component without nesting. The point of the feature I am proposing is precisely to be able to do your second snippet of code above without having to nest things, and here's how it'd be possible. <Composed components={[Counter, Timer]}>
{(counterProps, timerProps) => (
<YourComponent {...timerProps} {...counterProps} />
)}
</Composed> And this is indeed possible, as is evidenced in the code sandbox example I linked to above. |
can you post more concrete example what's your use case for this? |
Ok, at this point I think I may not be explaining my self correctly, but I'll try my best to attempt at explaining the need for this in more depth. The concept isn't at all new, and I was definitely not the one with the need in the first place. The tweet I mentioned at the beginning is one example of people needing this in various situations, now that render prop components are more and more popular and ubiquitous. Also the library react-powerplug which I already linked to, includes a similar utility component to achieve this exact same thing, but more oriented to work with all the render prop components that that library exposes, and not so much in the general case. Libraries like react-fns expose a lot of browser apis wrapped in a more declarative api based on render prop components. The powerplug one I mentioned above too. Imagine yourself leveraging stuff from several render prop components, all of them rendered because you need in the same place two or more of them. You'd have to nest them, and the excessive nesting quickly becomes unmanageable, often as early as three level deeps. A utility like the one I am proposing flattens that nesting of render prop components into a single one, which is sort of like composing them. |
Ok, I think I got your point and I agree, composing with render props components is really ugly :P that's why I still prefer HOC's for most cases. But let's wait what people smarter than me can say about this 😃 |
For the time being I plan to publish this as an independent library providing this feature alone. Thanks anyway for your feedback and your patience. I'll leave this issue open in case the discussion follows along. |
Thanks for your proposal. As what @pokorson said, Recompose is about higher-order components, so it seems weird to have a utility component for render-props components. |
I'm so confused. Is Also, unrelated, but are the components in this library available as transformers to compose inside a |
Here is another proposal making render props component composable in recompose way :) import { fromRenderProps } from 'recompose';
const { Consumer: ThemeConsumer } = React.createContext({ theme: 'dark' });
const { Consumer: I18NConsumer } = React.createContext({ i18n: 'en' });
const RenderPropsComponent = ({ render, value }) => render({ value: 1 });
const EnhancedApp = compose(
// Context (Function as Child Components)
fromRenderProps(ThemeConsumer, ({ theme }) => ({ theme })),
fromRenderProps(I18NConsumer, ({ i18n }) => ({ locale: i18n })),
// Render props
fromRenderProps(RenderPropsComponent, ({ value }) => ({ value }), 'render'),
)(App);
// Same as
const EnhancedApp = () => (
<ThemeConsumer>
{({ theme }) => (
<I18NConsumer>
{({ i18n }) => (
<RenderPropsComponent
render={({ value }) => (
<App theme={theme} locale={i18n} value={value} />
)}
/>
)}
</I18NConsumer>
)}
</ThemeConsumer>
) |
FYI - this library looks most popular right now for composing render props into a single component: |
This is motivated by this tweet by @acdlite and my shared need of such a feature, with my increasing tendency of heavily using render-props components.
I attempted an initial version of this, which can be seen working here. Here's an excerpt of what it looks like:
The above code would be equivalent to this lengthier code:
However, this just scratches the surface, because it does not support at least of couple of things that I anticipate it'll need:
render={() => ...}
prop or a<Wrapper>{() => ...}</Wrapper>
).I submit here the proposal so we can discuss if and how to provide these features, and the syntax and form with which such a composer can be provided by this library. For instance, I developed it as a render prop itself, but it might also be desirable to have it as a HOC, since most of this library exposes HOCs.
The text was updated successfully, but these errors were encountered: