/* Code-Comments */

Using isValidElement To Ensure A Node Is An Element In React

July 30, 2019

I am trying to reduce an array of React Nodes to an array of React Elements. Specifically, I’m trying to extract the title prop from those elements.

The problem is that a node has a much larger set of possible values than my Elements. Consequently, if I try to directly access my props to find the title, I run the risk of trying to access values that don’t exist.

For example:

export function extractTitles(accumulator: JSX.Element[], value?: React.ReactNode): JSX.Element[] {
    if (value.props.title) {
        accumulator.push(value.props.title);
    }
    return accumulator;
}
const titles: JSX.Element[] = nodes.reduce(extractTitles, []);

Typescript warns me about this upfront with the following warning:

Property 'props' does not exist on type 'string | number | boolean | {} | ReactElement<any, string | ((props: any) => ReactElement<any, string | ... | (new (props: any) => Component<any, any, any>)> | null) | (new (props: any) => Component<any, any, any>)> | ReactNodeArray | ReactPortal'.
  Property 'props' does not exist on type 'string'

The solution is simple: make sure that I’m not dealing with any of those other kinds of nodes before trying to access the title prop. To do this, React provides the top level API isValidElement which verifies the object is a React element.1

Updating my conditional, I’m able to only access those elements in my array that are elements and therefore have props.

import React from "react";

export function extractTitles(accumulator: JSX.Element[], value?: React.ReactNode): JSX.Element[] {
    if (React.isValidElement(value) && value.props.title) {
        accumulator.push(value.props.title);
    }
    return accumulator;
}

const titles: JSX.Element[] = nodes.reduce(extractTitles, []);

I’ve struggled with this problem a number of times before, but never quite grasped what I was looking at. Today, I made the time to dig a little deeper than in the past and it paid off — as it almost always does.

Footnotes


Stephen Weiss

Thanks for reading! My name's Stephen Weiss. I live in Chicago with my wife, Kate, and dog, Finn.
Click here to see the archives of my weeks in review and sign up yourself!