React sub-components Part 3: Whitelisting sub-components with flow
Adding more control to the sub-component pattern with Flow types
This small post is the continuation of my second article about sub-components. To fully understand this article please read that first
In Part 2 of my React sub-components series, we saw how using Context could greatly improve the original pattern I’ve described in my first post. However, one regression came along with this improvement and in this article we’ll bring a solution to it thanks to static typing.
The sub-component pattern described in the previous post addressed a few issues of the original implementation, but introduced one regression: children that are not properly defined as sub-components are still being rendered.
findByType util was being used to render our sub-components and would skip any unknown sub-components. The code snippet below shows this regression. You can give it a try by pulling the example project here and following the instruction in the README to run it. You can try switching the imports of
index.js to see how both implementation defer.
This regression breaks one of the main advantages of using sub-components: narrowing the scope of what can be rendered within a given component to make sure it is used properly and avoiding a messy codebase.
To fix this, as I mentioned at the end of the previous article, I decided to use static typing. The main idea here is to provide a specific
type for the
Article component, so that only a given list of components (i.e. our sub-components) will be rendered within it.
Flow to the rescue
Let’s see how static typing can fix the main caveat of the sub-component pattern that is implemented with contexts. I’m going to use Flow here to handle my types.
The gif below shows the actual implementation of using static typing to whitelist the sub-components of
Article . You can see that before adding
<div>Hello</div> as a child of
Article, running Flow against my codebase returns no errors. However, once I add this extra piece of code, Flow will output the following error:
Cannot create Article element because in property type of array element of
• Either div  is incompatible with typeof Title .
• Or div  is incompatible with typeof Metadata .
• Or div  is incompatible with typeof Content .
As you can see, Flow is aware of the type of our sub-components (and of any children of
Article ), and reports that
div is not compatible with one of these types.
To make sure to catch whether someone misuses
Article in our codebase, we can simply add Flow as a step in our CI pipeline. Additionally, there are many editor extensions available to highlight whenever a component is not use correctly given its Flow type.
How to achieve whitelisting with Flow
First, we need to add Flow to our project. For that, I recommend following this guide. Once done, running
flow at the root of the project should output no errors since we haven’t typed anything in our codebase yet.
Then we’ll need to do some modifications to our
Article.js file. First, we’ll have to change any sub-components declared as a functional component to a full class. This is due to the fact that classes have their own type but functional components do not. If we want to whitelist children, this is going to be the only limitation here.
Then, we’ll have to declare the types¹ of our sub-components, i.e. the children of
Article . For that we’ll declare a type
ArticleSubComponent which will be of type
Title or of type
Metadata or of type
Finally, we need to associate that type to the
children prop of
Article. Our component can have either 1 or more children, thus the type should either be an array of React elements of type
Article has 2 or more children or a single React element of type
ArticleSubComponent if it has 1.
The code snippet bellow shows the resulting component:
There are surely other solutions to address this issue, but this is the one I’m exploring as it uses dependencies and patterns that I’m already using in most of my projects.
Feeling like playing with Flow types and sub-components? I’ve made available this specific example on a branch named
flow on the same repository that I’ve used as an example for the previous post. Check it out here!
 The type reference doc from the Flow website was very useful when looking to type my classes https://flow.org/en/docs/react/types/#toc-react-element