Joris416
Joris416

Reputation: 4882

Using .tsx components in other .tsx components in React Native

I am teaching myself to build apps with TypeScript in React Native. As a Swift developer, JS and TS take a little bit of getting used to.

One thing I noticed is that is seems impossible to use a component I wrote in a tsx file inside another tsx file in the Render method.

//SomeComponent.tsx

export default class SomeComponent extends Component {
    //all my logic
}

//OtherComponent.tsx
export default class ScoreTable extends Component {
    //logic
    render() {

      <SomeComponent style={{flex: 1}}></SomeComponent>
    }
}

This would give me the following error:

Type '{ style: { flex: number; }; }' is not assignable to type 'IntrinsicAttributes & IntrinsicClassAttributes<SomeComponent> & Readonly<{}> & Readonly<{ children?: ReactNode; }>'.

I can resolve this issue by simply turning my tsx SomeComponent into a .js component, but I really like the tsx syntax. So my question is Why can't I use .tsx components in other tsx components? Or is there another way to do this?

Upvotes: 1

Views: 2339

Answers (2)

GregL
GregL

Reputation: 38121

I agree this error is confusing.

What's the problem?

Essentially, this is due to not specifying the type for the Props of SomeComponent correctly, leading TypeScript to assume the bare minimum type definition, which does not include a style property.

How do I fix it?

Add an interface for the props you expect to be accepted by SomeComponent, in much the same way as you might have previously done using PropTypes.

//SomeComponent.tsx

interface SomeComponentProps {
    style: React.CSSProperties;
}

export default class SomeComponent extends Component<SomeComponentProps> {
    //all my logic
}

How did you figure that out?

There are a few clues. The first is the Type '{ style: { flex: number; }; }' part, which looks an awful lot like the attributes (a.k.a. props) you specify when using SomeComponent in OtherComponent.tsx. So it probably has something to do with props for SomeComponent.

The next part of the error says is not assignable to type, confirming that TypeScript thinks the type of the props doesn't match what it knows about SomeComponent.

The final part of the error is the most confusing, where it lists the type 'IntrinsicAttributes & IntrinsicClassAttributes<SomeComponent> & Readonly<{}> & Readonly<{ children?: ReactNode; }>'. Searching for IntrinsicAttributes in my React code allowed me to see that it was indeed to do with the base type of the attributes expected by a component (I found it in node_modules/@types/react/index.d.ts, the type definitions for react).

Combining all of these clues with the prior knowledge of how to strongly type the props and state of custom react components in TypeScript using the two optional generic type params to React.Component lead me to the final solution.

Hopefully you now feel more empowered to decipher similarly confusing error messages in future.

Upvotes: 1

Donovan Hiland
Donovan Hiland

Reputation: 1499

You need to define style as a prop that your SomeComponent accepts:

import React, { Component, CSSProperties } from "react";

interface Props {
  style: CSSProperties;
}

export default class SomeComponent extends Component<Props> {

Upvotes: 1

Related Questions