Reputation: 68750
In this simple component, I pass in MyProps which looks like this:
interface MyProps {
profiles: IProfile[]
}
interface IProfile {
name: string;
avatar_url: string;
company: string;
}
My component defines props as MyProp
, but the Typescript compiler complains that this.state.profiles does not exist on type Readonly<{}>
:
class App extends React.Component<MyProps> {
constructor(props: MyProps) {
super(props);
this.state = { profiles: props.profiles };
}
public render() {
return (<div>//ERROR HERE
{this.state.profiles.map((profile: IProfile) => <Card {...profile} />)}
</div>);
}
};
If I set the second field to any or MyProps it works. Do I always need to define the first 2 params of the React.Component?
class App extends React.Component<MyProps,MyProps>
Upvotes: 0
Views: 628
Reputation: 2302
I just want to expand slightly on the already provided answer.
Until relatively recently you ALWAYS had to supply both the Props type and the State type to the Component<P,S>
generic type, so class App extends React.Component<MyProps>
would have been an error, saying you need to supply a type for State.
Now, Typescript supports defaulting generic types, and the React types make use of this by defining:
interface Component<P = {}, S = {}, SS = any> extends ComponentLifecycle<P, S, SS> { }
This means that you no longer are required to always provide types for Props and State, and if you do not provide types, they will default to the type {}
, which is an object with no properties. As the property profiles
does not exist on the type {}
, you get the type error you are observing.
I only raise this distinction because the actual answer to your question is no, because of generic type defaulting, you do not always need to define the first two params of React.Component
. But if you do not supply them they will be defaulted to the type {}
, which has no properties. So, you must supply the Props and State type if you are going to be making use of Props and State inside your component.
Upvotes: 1
Reputation: 42536
Within TypeScript,
React.Component
is a generic type (aka
React.Component<PropType, StateType>
)
Since you are defining state within that component, you will need to create an interface for your state for typechecking.
interface MyState {
profiles: IProfile[];
}
After creating that, you can supply that to your React.Component
class App extends React.Component<MyProps, MyState> {
constructor(props: MyProps) {
super(props);
this.state = { profiles: props.profiles };
}
public render() {
return (<div>//ERROR HERE
{this.state.profiles.map((profile: IProfile) => <Card {...profile} />)}
</div>);
}
};
Upvotes: 2