Ochuko Onojakpor Ochuko is a full-stack Python/React software developer and freelance Technical Writer. He spends his free time contributing to open source and tutoring students on programming in collaboration with Google DSC.

Using the React children prop with TypeScript

4 min read 1241

Using The React Children Prop With TypeScript

By invoking them between the opening and closing tags of a JSX element, you can use React children for entering data into a component.

The React children prop is an important concept for creating reusable components because it allows components to be constructed together.

However, a common issue with using React with Typescript is figuring out which data type to use with React children since Typescript is a strongly typed library. So, in this article, we will learn how to utilize props with React children in Typescript.

Using React children props

Before learning how to use Typescript with React children, let’s refresh our memories on how to use the React children props and how they work.

What are React props?

Props is simply an abbreviation for properties. In React, we utilize props to send data from one component to another (from a parent component to a child component or multiple children components).

They come in handy when you want the data flow in an app to be dynamic. Below is an example of using props to pass data using props.

function House(props) {
  return <h2>I am a { props.type }!</h2>;
}

function Room() {
  return (
    <>
      <h1>Do you know my room number?</h1>
      <House type="duplex" />
    </>
  );
}

Here, we passed data to the type property in the House component. This property type is called a prop. In this example, the parent component is Room, while the child component is House.

The type property we passed then renders in the House component to return I am a duplex.

What are React children props?

The ability for components to receive and render children props is one of React’s most valuable features. It makes creating reusable components insanely simple. Simply encapsulate props.children with some markup or action and you’re done:

function House(props) {
  return <h2>I am a { props.children }!</h2>;
}

function Room() {
  return (
    <>
      <h1>Do you know my room number?</h1>
      <House type="duplex" />
    </>
  );
}


const Panel = (props) =>
  <div className="Panel">
    {props.children}
  </div>

Using React children props with Typescript

Typescript is a type-strict JavaScript library, which means you must define the types for your React children props, and there are different methods of declaring types for React children props. Let’s learn some of them.

We made a custom demo for .
No really. Click here to check it out.

Using the FC type

FC is a standard React type used in arrow function components, also known as the FunctionComponent type.

Here’s an illustration:

type Props = {
  title: string,
};
const Page: React.FC<Props> = ({
  title,
  children,
}) => (
  <div>
    <h1>{title}</h1>
    {children}
  </div>
);

FC is a general type that accepts all component props and their individual types. In this example, we supplied a Props type alias with a title prop.

It’s worth noting that you don’t define the term children in Props, since it’s already defined in the functional component type.

Defining the children prop type explicitly

If we declare the children prop type directly, we will have different options to set for its type. Let’s take a look at how we can declare the children prop type directly.

Using a JSX element

Consider the code sample where we used JSX elements below:

type Props = {
  title: string,
  children: JSX.Element,
};
const Page = ({ title, children }: Props) => (
  <div>
    <h1>{title}</h1>
    {children}
  </div>
);

Here, children are a necessary field. To make this optional for the component’s consumer, we can include a question mark (?) before the type annotation, as seen in the example below:

type Props = {
  title: string;
  children?: JSX.Element;
};

If the child must be a single React element, using JSX.Element is appropriate. It does not, however, permit several children. As a result, we can make the following change:

type Props = {
  title: string;
  children?: JSX.Element | JSX.Element[];
};

Using ReactChild

One disadvantage of JSX.Element is that it does not support strings. As a result, we can include strings in the union type:

type Props = {
  title: string;
  children:
    | JSX.Element
    | JSX.Element[]
    | string
    | string[];
};

However, the example above does not cover number types. So what do we do?

Fortunately, ReactChild is a standard type that includes React components, strings, and integers. As a result, we can broaden the type for children as follows:

type Props = {
  title: string;
  children?:
    | React.ReactChild
    | React.ReactChild[];
};

Using ReactNode

React.ReactChild or React.ReactChild[] provides the necessary breadth of values but is a little verbose. ReactNode is a more succinct option:

type Props = {
  title: string;
  children?: React.ReactNode;
};

ReactNode supports multiple elements, strings, integers, fragments, and portals.

Class components

What if we want to use a class component instead of a functional one? Let’s see how we can handle it:

type Props = {
  title: string,
};
export class Page extends React.Component<Props> {
  render() {
    return (
      <div>
        <h1>{this.props.title}</h1>
        {this.props.children}
      </div>
    );
  }
}

The component type, like the FC type, includes the children prop by default.

When we hover over the children prop, we can see what type it has, as seen in the image below:

Children Prop

So, the type of the children prop in a class component is ReactNode.

List of types for React component props

Here’s a list of types you might want to utilize in your React application using Typescript. Some of them are:

  • Primitive types, such as string
  • Numeric type
  • Boolean type
type Props = {
  // primitive types
  title: string,
  score: number,
  isWinning: boolean
}

You can also make an array of a single type by appending the array literal notation ([]) to the end of the type:

type Props = {
  title: string[], // an array of string
  score: number,
  isWinning: boolean
}

You can also use literal values to describe the precise values that the prop can allow.

You must use a single pipe operator (|) to divide the literals, as seen below:

type Props = {
  priority: "high" | "normal" | "low",
  score: 5 | 9 | 10
}

When the value of the priority or score prop above does not match any of the literal values, TypeScript will throw a static error.

After that, you can type an object prop like this:

type Props = {
  user: {
    username: string,
    age: number,
    isMember: boolean
  }
}

Simply add the array literal notation to the end of the object declaration when you have an array of objects prop:

type Props = {
  user: {
    username: string,
    age: number,
    isMember: boolean
  }[] // right here
}

You may need to type function props since React props can also accept functions like onClick and onChange.

You can either input the function’s arguments or get an event object from the HTML, as seen below:

type Props = {
  // function that returns nothing
  onClick: () => void,
  // function accepts a parameter and has return type
  onChange: (target: string) => boolean,
  // function that takes an event
  handleSubmit: (event: React.FormEvent<HTMLFormElement>) => void
}

If you declare an onChange function in the component’s body, you can instantly examine the function’s parameter and return types, as demonstrated below:

const App = () => {
  const [message, setMessage] = useState("")
  
  const onChange = (e: React.FormEvent<HTMLInputElement>): void => 
    {
      setMessage(e.currentTarget.value);
    }

}

These are the most frequent React prop types we have in Typescript.

Conclusion

The children prop will become automatically typed if you use function components with the FC type. The ReactNode type is often the best choice if you explicitly specify the children prop.

Full visibility into production React apps

Debugging React applications can be difficult, especially when users experience issues that are hard to reproduce. If you’re interested in monitoring and tracking Redux state, automatically surfacing JavaScript errors, and tracking slow network requests and component load time, try LogRocket.

LogRocket is like a DVR for web and mobile apps, recording literally everything that happens on your React app. Instead of guessing why problems happen, you can aggregate and report on what state your application was in when an issue occurred. LogRocket also monitors your app's performance, reporting with metrics like client CPU load, client memory usage, and more.

The LogRocket Redux middleware package adds an extra layer of visibility into your user sessions. LogRocket logs all actions and state from your Redux stores.

Modernize how you debug your React apps — .

Ochuko Onojakpor Ochuko is a full-stack Python/React software developer and freelance Technical Writer. He spends his free time contributing to open source and tutoring students on programming in collaboration with Google DSC.

Leave a Reply