Useful React APIs For Building Flexible Components With TypeScript
About The Author
Gaurav Khanna works at Superadmin.so — a fully-remote startup working to make visual testing easier. An experienced engineer, active in the tech and …
React with JSX is a fantastic tool for making easy-to-use components. Typescript components make it an absolute pleasure for developers to integrate your components into their apps and explore your APIs. Learn about three lesser-known React APIs that can take your components to the next level, and help you build even better React Components in this article.
Have you ever used
React.createElement directly? What about
React.cloneElement? React is more than just transforming your JSX into HTML. Much more, and to help you level up your knowledge of lesser-known (but very useful) APIs the React library ships with. We’re going to go over a few of them and some of their use cases that can drastically enhance your components’ integration and usefulness.
In this article, we’ll go over a few useful React APIs that are not as commonly known but extremely useful for web developers. Readers should be experienced with React and JSX syntax, Typescript knowledge is helpful but not necessary. Readers will walk away with everything they need to know in order to greatly enhance React components when using them in React applications.
Most developers may never have heard of
cloneElement or ever used it. It was relatively recently introduced to replace the function.
cloneElement clones an element, it also lets you merge new props with the existing element, modifying them or overriding them as you see fit. This opens up extremely powerful options for building world-class APIs for functional components. Take a look at the signature.
Here’s the condensed Typescript version:
You can take an element, modify it, even override its children, and then return it as a new element. Take a look at the following example. Let’s say we want to create a TabBar component of links. That might look something like this.
The TabBar is a list of links, but we need a way to define two pieces of data, the title of the link, and the URL. So we’ll want a data structure passed in with this information. So our developer would make our component like so.
This is great, but what if the user wants to render
button elements instead of
a elements? Well, we could add another property that tells the component what type of element to render.
But you can see how this will quickly get unwieldy, we would need to support more and more properties to handle various use cases and edge cases for maximum flexibility.
Here’s a better way, using
We’ll start by changing our interface to reference the
ReactNode type. This is a generic type that encompasses anything React can render, typically JSX Elements but also can be strings and even
null. This is useful for designating you to want to accept React components or JSX as arguments inline.
Now we’re asking the user to give us some React Elements, and we’ll render them how we want.
This is perfectly valid and would render our elements. But we’re forgetting a couple of things. For one,
key! We want to add keys so React can render our lists efficiently. We also want to alter our elements to make necessary transformations so they fit into our styling, such as
className, and so on.
We can do these with
React.cloneElement, and another function
React.isValidElement for checking the argument conforms to what we’re expecting!
Meet Image Optimization, Addy Osmani’s brand new practical guide to optimizing and delivering high-quality images on the web. From formats and compression to delivery and maintenance: everything in one single 528-pages book.
This function returns
true if an element is a valid React Element and React can render it. Here’s an example of modifying the elements from the previous example.
Here we’re adding a key prop to each element we’re passing in and making every link bold at the same time! We can now accept arbitrary React Elements as props like so:
The advantage here is if we wanted to set a custom
onClick handler to our button, we could do so. Accepting React elements themselves as arguments is a powerful way to give flexibility to your component design.
useState Setter Function
Use Hooks! The
useState hook is extremely useful and a fantastic API for quickly building state into your components like so:
In certain situations, a variable might not be the correct value because of the context it is in, such as in for-loops commonly or asynchronous events. This is because of lexical scoping. When a new function is created the lexical scope is preserved. Because there is no new function, the lexical scope of
newVal is not preserved, and so the value is actually dereferenced by the time it is used.
What you’ll need to do is utilize the setter as a function. By creating a new function the variables reference is preserved in lexical scope and the currentVal is passed in by the React useState Hook itself.
This will ensure that your value is updated correctly because the setter function is called in the correct context. What React does here is call your function in the correct context for a React state update to occur. This can also be used in other situations where it’s helpful to act on the current value, React calls your function with the first argument as the current value.
Note: For additional reading on the topic of async and closures, I recommend reading “ Lazy Initialization And Function Updates” by Kent C. Dodds.
JSX Inline Functions
Here’s a Codepen demo of a JSX inline function:
See the Pen [Hello World in React](https://codepen.io/smashingmag/pen/QWgQQKR) by Gaurav Khanna.
Not exactly a React API per-say.
Here’s an example:
Here we’re declaring code inside of JSX, we can run arbitrary code and all we have to do is return a JSX function to be rendered.
We can make it conditional, or simply perform some logic. Take note of the parentheses surrounding the inline function. Also particularly here where we are calling this function, we could even pass an argument into this function from the surrounding context if we wanted to!
This can be useful in situations where you want to act on a collection data structure in a more complex way than a standard
.map allows for inside of a JSX element.
Here we can run some code to loop through a set of numbers and then display them inline. If you use a static site generator such as Gatsby, this step would be pre-computed as well.
component extends type
Immensely useful for creating autocomplete-friendly components, this feature allows you to create components that extend existing
Here’s a simple example, let’s say we want to override one or two properties of a
button element, but still give developers the option to add other properties to the button. Such as setting
type='submit'. We obviously don’t want to recreate the entire button element, we just want to extend its existing properties, and maybe add one more prop.
First we import React and the class, a type that encompasses the props of a
HTMLButtonElement. You can read the source code for this type of interface here:
And you can see the React team has reimplemented all of the web’s APIs in TypeScript so can be type-checked.
Next, we declare our interface like so, adding our
And finally, we do a couple of things. We use ES6 destructuring to pull out the props that we care about (
children), and declare any other properties as
rest. And in our JSX output, we return a button element, with ES6 structuring to add any additional properties to this element.
So now a developer can add a
type prop or any other prop that a button would typically have. We’ve given an additional prop that we’ve utilized in the
className to set the style of the button.
Here’s the entire example:
This makes for a great way of creating reusable internal components that conform to your style guidelines without rebuilding entire HTML elements! You can simply override entire props such as setting the
className based on the status or allow for additional class names to be passed in as well.
Here we take the prop
className passed to our Button element, and insert it back in, with a safety check in the case of the prop being
React is an extremely powerful library, and there’s a good reason why it has quickly gained popularity. It gives you a great tool-set to build performant and easy-to-maintain web apps. It’s extremely flexible and yet very strict at the same time, which can be incredibly useful if you know how to use it. These are just a few APIs that are noteworthy and are largely overlooked. Give them a try in your next project!
For further reading about the latest React APIs, hooks, I would recommend reading useHooks(?). The Typescript Cheatsheet also has some great information for React and Typescript Hooks.
(ks, vf, yk, il)
This content was originally published here.