-
Notifications
You must be signed in to change notification settings - Fork 562
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
Add React.Children.isRenderable #11
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
- Start Date: 2018-01-10 | ||
- RFC PR: (leave this empty) | ||
- React Issue: (leave this empty) | ||
|
||
# Summary | ||
|
||
Add React.Children.isRenderable() method which returns `boolean` depending | ||
on whether a passed child returns `ReactNode` or not. | ||
|
||
# Basic example | ||
|
||
`React.Children.isRenderable` lets us easily detect children without UI. | ||
```js | ||
const MaybeWrapper = ({children}) => | ||
React.Children.map(children, child => | ||
React.Children.isRenderable(child) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I am not sure why you want this method on There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That might be convenient when we use it for whatever is passed to |
||
? <Wrapper>{child}</Wrapper> | ||
: child | ||
) | ||
``` | ||
|
||
# Motivation | ||
|
||
Given a component which renders markup or `null` depending on its props there | ||
are cases when we want to know whether it renders something: | ||
- if we need to wrap it with layout, or draw something else around or add | ||
animations, etc and don't want to break styling with excessive wrappers; | ||
- if we want to show a placeholder when the component has not been rendered; | ||
- if we want to count actually visible children in an array. | ||
|
||
`React.Children.isRenderable` would allow us easily check if a component | ||
renders anything without messing up it's internals. It is simple, useful and | ||
plays well with other methods from `React.Children` namespace. | ||
|
||
# Detailed design | ||
|
||
A method takes a `child` component instance, finds it's corresponding fiber and | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: it's -> its |
||
checks whether it has a `stateNode`. If a `stateNode` exist, the method returns | ||
`true`, else it starts recursively repeat this process on a child fiber and it's | ||
siblings until it finds a non-empty `stateNode` containing a DOM node, otherwise | ||
it returns `false`. | ||
|
||
# Drawbacks | ||
|
||
Why should we *not* do this? Please consider: | ||
|
||
- the proposed feature can be implemented in user space | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could you elaborate on how would this be achievable in user space? Perhaps if it can be shown that it would be complex enough to do so, it could help your case. For instance, it may be naivety on my side, but I'm not sure how |
||
|
||
# Alternatives | ||
|
||
Obviously, we could store the result of the rendering condition in the | ||
component's state, update it when props change and check passing handler from | ||
a parent or we could hoist condition to a parent but we might not want do | ||
anything of that because: | ||
- the component may receive props from context (e.g. from Redux store via | ||
`connect` function) so we cannot hoist the condition; | ||
- adding props for "renderability" handler to the component may break coherence; | ||
- we may not be able to modify the component's internals (e.g. it is from a 3rd | ||
party library); | ||
- we don't want to add complexity for a trivial action (e.g. we have | ||
a stateless functional component with rendering condition. Do we really need | ||
to make it stateful just to check if it renders anything?) or lose | ||
convenience (stateless conditional components are quite eloquent). | ||
We could also use refs to check if a component was rendered, but this is even | ||
more messy solution than previous. | ||
|
||
# How we teach this | ||
|
||
To understand why this feature is useful and how it should be used, a user | ||
must be familiar with core React concepts covered in [React Components, Elements, and Instances](https://reactjs.org/blog/2015/12/18/react-components-elements-and-instances.html) | ||
|
||
# Unresolved questions | ||
|
||
Another possible solution might be to create a method, which returns a complete | ||
Node (or `null`), rendered by the passed child though such functionality may | ||
lead to misuse and confusion. Also that would probably have some performance | ||
drawbacks because it requires to traverse deeper into a fiber. | ||
|
||
The name of this method might be reconsidered. The alternatives are: | ||
`hasNode`, `hasReactNode`, `rendersNull` (then should return `false` if | ||
renders anything). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would perhaps revise the naming to something like
React.Children.hasRenderedOutput
. Components that render nothing are still "renderable" if that makes sense.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agree