Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Component which prop must be an array of specific React elements

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

like image 999
David Gomes Avatar asked Jul 22 '21 21:07

David Gomes


People also ask

Can a React prop be an array?

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!

Can you have an array of React components?

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.

What is props component in React?

Props are arguments passed into React components. Props are passed to components via HTML attributes. props stands for properties.

What are props in react?

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

What is a React component?

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.

How do I add proptypes to a React component?

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({ ...

Can you change the value of a prop in react 6?

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.


2 Answers

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

like image 102
Codebling Avatar answered Oct 23 '22 08:10

Codebling


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" }]} />
);
like image 25
Subrato Pattanaik Avatar answered Oct 23 '22 08:10

Subrato Pattanaik