I'm trying to write a component which accepts an array of instances of another component as a prop. That component is MyComponent
, which accepts an array of instances of Title
as one of its arguments. However, I am not able to get TypeScript to type check this:
import * as React from "react";
type TitleProps = {
name: string;
};
function Title(props: TitleProps) {
return null;
}
type MyComponentProps = {
titles: Array<React.ReactElement<TitleProps>>;
}
function MyComponent({ titles }: MyComponentProps) {
return <div>{titles}</div>;
}
function OtherComponent(props: {}) { return null }
const shouldError = <MyComponent titles={[ <div/>, <OtherComponent/> ]} />;
const shouldNotError = <MyComponent titles={[ <Title name="hi"/>, <Title name="hi2"/>, ]} />;
As you can see, I am able to pass whatever I want to the titles
prop, not just instances of <Title/>
.
TypeScript Playground URL
To pass an array as a prop to a component in React, wrap the array in curly braces, e.g. <Books arr={['A', 'B', 'C']} /> . The child component can perform custom logic on the array or use the map() method to render the array's elements. Copied!
To render an array of components in React you simply need to pass the array into JSX by wrapping it in curly braces, just be sure that your components each have a unique key prop because React will use this when rendering it to avoid bugs.
Props are arguments passed into React components. Props are passed to components via HTML attributes. props stands for properties.
When React sees an element representing a user-defined component, it passes JSX attributes and children to this component as a single object. We call this object “props”. For example, this code renders “Hello, Sara” on the
This page provides an introduction to the idea of components. You can find a detailed component API reference here. Conceptually, components are like JavaScript functions. They accept arbitrary inputs (called “props”) and return React elements describing what should appear on the screen.
Add PropTypes directly to the component function. In JavaScript, functions are objects, which means you can add properties using dot syntax. Add the following PropTypes to AnimalCard.js: import React from 'react'; import PropTypes from 'prop-types'; import './AnimalCard.css' export default function AnimalCard({ ...
6. Update a React prop's value with state Props cannot be directly updated. To pass a prop value to a component, we cannot within that function component attempt to immediately change that prop's value. Prop values must be pure values. In other words, they cannot be mutated or changed directly.
TypeScript is not a silver bullet. There are a number of cases in which guaranteeing 100% type safety requires the introduction of additional complexity in the code, or is simply impossible. You have encountered one such situation.
There is an open GitHub issue on the subject of typing JSX elements. Your best bet is to wait for TypeScript to introduce a specific mechanism for this.
Otherwise (from Matt McCutchen's answer):
all JSX elements are hard-coded to have the JSX.Element type, so there's no way to accept certain JSX elements and not others. If you wanted that kind of checking, you would have to give up the JSX syntax, define your own element factory function that wraps React.createElement but returns different element types for different component types, and write calls to that factory function manually.
So as of right now there is no way to ensure type safety for any JSX elements
The feature of type safety for
JSX.Element
in Typescript is not available to us yet.
We had this similar scenario before and what we did is instead of having an array of JSX.Element
, we use an array of props that the same element can have. Then during render, we simply map the array of props to the array of JSX.Element
.
import * as React from "react";
type TitleProps = {
name: string;
};
function Title(props: TitleProps) {
return null;
}
type MyComponentProps = {
titles: TitleProps[];
};
function MyComponent({ titles }: MyComponentProps) {
return (
<React.Fragment>
{titles.map(titleProps => (
<Title {...titleProps} />
))}
</React.Fragment>
);
}
// no errror
const shouldNotError = (
<MyComponent titles={[{ name: "React" }, { name: "fixme" }]} />
);
//error
const shouldError = (
<MyComponent titles={[{ other: "don't use this" }, { another: "help" }]} />
);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With