-
Notifications
You must be signed in to change notification settings - Fork 54
Alternative to 'renderX' set of props for slots #355
Comments
@kuzhelov thanks for the detailed RFC, pointing the issues of the current implementation and providing alternative one. 1. Avoiding the necessity to bloat the APIFirst, I would really appreciate if we can avoid the necessity to bloat the API with adding new property for each slot inside each component. Apart from this, the user will only have to remember just one usage of the shotrhand, and not having to make a decision about which one he/she should use, which I am sure will result in much cleaner and bug-free code. 2 Avoiding the 'Do it yourself' patternAs a second point, I would mention your first point for avoiding 'Do it yourself' pattern, which again in the current implementation can lead to bugs that, for the user, may be hard to be located. ConclusionWith this being said, and the examples provided, we can be sure that the proposed API looks much promising then the initial implementation. However we must consider that, the initial implementation is so far used by the client, and it is working as expected. If we go with this implementation, which I really think we should, we should provide very clean instructions about how the initial implementation should be migrate to the new one, and of course we should be sure that we won't reduce some of the functionality of the initial implementation (I am not saying that we are, but I haven't seen the implementation of the second one, and this is something that we just can't do). |
Thank you @kuzhelov for putting this detailed proposal together. If I understand it correctly, it it's most basic form On a side note regarding async rendering: Have we considered the react suspense API for Async components. It is still experimental, but since it is throwing Promises, it seems possible to surface data from a child component up to a parent, causing the parent to re-render with the new set of data. (cc: @levithomason) |
So others know, @kuzhelov is working on implementing this. Could you link the PR here if/once it is up? |
@kohlikohl, sorry for the late response on that. Let me, please, address two main concerns/questions you've raised:
yes, exactly - as you've mentioned, in the basic case <Button icon={render => {
const additionalProps = getAdditionalProps(...)
return render({ name: 'user', ...additionalProps })
} /> or if rendered tree should be in full control (like it was always the case for <Button icon={render => {
const additionalProps = getAdditionalProps(...)
return render({ name: 'user' }, (Component, props) => <Component {...props} {...additionalProps} />)
} />
Absolutely - actually, generally speaking, any approach that would be about hoisting state to state management parent component (that will propagate updated data to its children) is a preferred approach in comparison to On a side note - at the present moment it is clearly seen (according to tweets and blog posts of React community) that this Suspense feature will be introduced almost for certain (unless if only some critical flaw would be found) :) |
closed by #519 |
Let this issue serve as a discussion hub for alternative approach to
renderXXX
one that is currently used for Stardust components.TL;DR Here is the list of main reasons for that:
renderXXX
renderXXX
methods for each slot of each componentPlease, note that scenario-based comparison examples for both approaches are also provided.
Contents
Motivation
There are several problems with current `renderItem` prop - let me mention them.1. "Do It Yourself" pattern provided by `renderXXX` to compose component
Lets consider the API we now have for
renderItem
:As we might see, there are quite a lot of things that client should worry about now - thus, this approach is quite error-prone.
2. Shorthand is evaluated at different stage for async case
For synchronous case we've had that shorthand item was rendered after its descriptor object (i.e. element of
items
array) has been fully initialized.Now lets move to async case. For the sake of example lets suppose that we have only
key
data being defined for each item, and thatcontent
data should be fetched for it.With
renderItem
approach we have shorthand(Component, props)
evaluation happened before data is fetched - while, to comply with synchronous semantics of shorthand, we need this evaluation to happen after necessary data is fetched. Note that this might be absolutely necessary if shorthand evaluation relies on some data that is fetched asynchronously.3. Bloat of additional props needed for each component
With
renderXXX
approach we need to introduce newrender
function for each slot of each component. With the alternative approach there won't be any need to supportrender
functionality on the component's side - once written it will be automatically reused by all components.4. Points of general confusion for client
General question that immediately arises for
renderXXX
approach is how shorthand's object data is passed torenderItem
? It turns out that all theitem
's data is merged into component'sprops
provided in the callback - arguably, not something very intuitive for the client.Proposed Solution
General Idea
TL;DR General idea is to support callback function for shorthand, where
render
function as an argument.Full Story
Stardust has a notion of
shorthand
to provide a declarative way for specifying components that should be rendered - in a form of object or React Element. Specifically, for the following case we have aMenu
whichitems
array is declared by object shorthands used:However, at the very end each object is evaluated to React Element when
Menu
is rendered. Thus, the following one will provide identical results: here each object ofitems
array is transformed toMenuItem
element (with necessary props being evaluated and properly applied).So, essentially, we could imagine some
transformShorthandObject
function that produces React Element from the object provided - and this is, essentially, the only piece hidden from the client when shorthand is provided in a form ofobject
. This hidden piece,render
(transformShorthandObject
) function, is the corner stone of the proposed approach.Example
Essentially, these two will provide identical rendered
Menu
:Benefits
renderXXX
prop for all slots of all componentsrenderXXX
approach mentioned aboveScenario Examples
Explain concept to consumer
Suppose that we have the following code as the originally written. Following example provide identical effect as this original one.
Before
Proposed
Thoughts
items
are used inrenderItem
props
to element.item
) is utilized for the alternative proposal - this will prevent potential inconsistent use of twoitems
andrenderItem
props that are dependent on each other now.Async Rendering
Suppose that client's intent is to render each item's shorthand asynchronously, once all the necessary shorthand data is fetched.
Also, for the sake of argument, suppose that client's code have some component that provides abstraction for data fetching logic - e.g.
Async
, that provides the following basic propsgetData
- defiines logic for async data fetchingrender
- defines logic to render tree once data is fetchedBefore
Proposed
Thoughts
render
method), semantics remain to be the same: once shorthand descriptor object is fully ready, pass it to therender
method to evaluate the shorthand. WithrenderXXX
approach we see the shorthand object being precomputed first (implicitly, based on theitem
), decomposed toComp
andprops
- and when async operation finishes, its client responsibility to properly compose the object back. Thus, with the only need of async rendering being introduced, client is provided with additional irrelevant responsibility to properly compose the element.url
directly as prop of the item initems
array, as what intuitive thought would be - because in that case this will be merged toprops
that are passed inrenderItem
callback. Thus there is a need to introduce thiskeyToUrl
mapper.Custom Tree Rendering
Before
Proposed
OPTION 1: Identical approach, use the same
Comp
,props
tools so that the same set of cases could be addressed.OPTION 2: Safer approach
Thoughts
<Component {...props} />
part - and this what is guaranteed to be properly handled by alternative approachrender
function - and, thus, it is possible to fully cover the same scenarios that are possible now.Selectively apply special rendering
In this example lets suppose that our need is to fetch data for only one/several elements of
Menu
- and lets suppose that we have to use theAsync
component for that (for example, in case of Apollo-based app).Before
Proposed
Thoughts
renderItem
prop case (the one we have now) - this will result inswitch
semantics being needed from client - either byif
-switch
expressions, or by using dedicated map object.The text was updated successfully, but these errors were encountered: