React Top Level API
01 March 2022
Updated: 03 September 2023
For a reference on the React Top-Level API you can take a look at the React Docs
Introduction
React allows us to do lots of different things using concepts like composition and higher order components. Most of the time these methods are good enough for us to do what we want, however there are some cases where these methods can prove to be insufficient such as when building complex library components or components that need to allow for dynamic composition or do runtime modification of things like child component props, etc.
For the above purposes we can make use of the React Top-Level API. For the purpose of this writeup I’ll be making use of the parts of this API that allow us to modify a component’s children and modify their props as well as how they’re rendered
Our Goal
For the purpose of this doc I’ll be using the React API to get to do the following:
- Show the count of children (
Items
) passed to a component (Wrapper
) - Render each child in a sub-wrapper
ItemWrapper
- Modify the props of the children by adding a
position
prop
When this is done, we want to render a component that results in the following markup:
But a consumer can be used like:
Using React.Children
to work with a component’s children
The React.Children
API (see docs) provides us with some utilities for traversing the children passed to a component
Before we can do any of the following, we need to define the structure of an item. Our Item
component is defined as follows:
Use React.Children.count
to get the count
The React.Children.count
function counts the number of child nodes passed to a React component,
we can use it like so:
For our example, let’s start off by creating a Count
component that simply takes a count
prop and displays some text:
Next, we can define our Wrapper
which will take children
and pass the count
to our Count
component:
Use React.Children.map
to wrap each child
Next, the React.Children.map
function allows us to map over the children of an element and do stuff with it, for example:
Based on the above, we can define an ItemWrapper
as so:
And we can update the Wrapper
to make use of React.children.map
:
Use React.cloneElement
to change child props
Lastly, we want to append a position
prop to the Item
. To do this we can make use of the React.cloneElement
function which allows us to clone an element and modify the props of it. Using this function looks like so:
Integrating this into the React.Children.map
function above will result in our Wrapper
looking like so:
Use React.isValidElement
We’ve completed most of what’s needed, however if for some reason our child
is not a valid react element our component may still crash. To get around this we can use the React.isValidElement
function
We can update our map
function above to return null
if the element is not value:
Which results in our Wrapper
now being:
The Result
Lastly, we’ll render the above using the App
component, the API for the above components should be composable as we outlined initially. The App
component will now look like so:
And the rendered HTML:
Total: 3
-
Apple, 0
-
Banana, 1
-
Chocolate, 2
And lastly, if you’d like to interact with the code from this sample you can see it in this Repl