In this blog post, I intend to demonstrate how to implement a Heading component that given a prop value, renders a heading element. To achieve just that I am going to use Typescript to enforce the component’s API, and React.createElement
.
The API
Nowadays it's common for React's styling libraries to provide a component that enables developers to define the exact kind of heading element they want the application to render, and on this post, I plan to achieve the same:
<!-- H1 -->
<Heading as="h1">The HTML Section Heading elements</Heading>
<!-- H2 -->
<Heading as="h2">Examples</Heading>
Component structure
import React from "react";
interface Props extends Partial<Omit<HTMLHeadingElement, "children">> {
children: string;
as?: "h1" | "h2" | "h3" | "h4" | "h5" | "h6";
}
export function Heading({ as = "h1", children, style }: Props) {
return React.createElement(as, { ...style }, children);
}
Firstly, In order to move away from a switch statement with multiple declarations of heading elements, I have decided to use React.createElement
API because it enables the developer to pass a string stating which tag should be created.
Secondly, I have used Typescript’s union type feature to enforce the component’s consumer to pass a valid heading element’s name.
Extends, Partial and Omit
interface Props extends Partial<Omit<HTMLHeadingElement, "children">> {}
In case you wondered what is this block of code doing, here is the explanation: I needed to inherit all the attributes of heading elements, hence the extends
statement. However, I did not want to make them explicitly mandatory, therefore I have used the Partial
type to make all the properties defined in HTMLHeadingElement
interface optional. I wanted one more thing, which was to override the children
property from the interface aforementioned, therefore I have used the Omit
type to achieve that.
Conclusion
This was a rather simple implementation of a component leveraging React.createElement()
, which is the API behind JSX, and Typescript to enforce an API that enable developers to choose the exact kind of heading element they intend to use.