Reputation: 2047
I have created a React component that takes a class of its child component. This component is responsible for providing the user ability to login via the OIDC protocol and if the user is logged in – rendering the child passing the user object as a prop (the child would use it in API calls).
This is how my component is declared:
type AuthProps = {
childClass: typeof React.Component;
}
type AuthState = {
user: Maybe<User>
}
class Auth extends React.Component<AuthProps, AuthState> {
}
Then I render my child element like:
<this.props.childClass user={this.state.user} />
This configuration works just fine. But what if I wanted more type safety? Namely if I want to ensure that childClass
supports the user
prop? I tried to type it like:
childClass: typeof ReactComponent<{user: Maybe<User>}>,
this, however is not even a proper syntax. Is it possible to narrow the type of childClass
somehow?
Upvotes: 0
Views: 53
Reputation: 74770
Alternative 1: React.ComponentType
type AuthProps = {
childClass: React.ComponentType<{ user: Maybe<User> }>;
};
class Auth extends React.Component<AuthProps, AuthState> {
render() {
return <this.props.childClass user={this.state.user} />;
}
}
React.ComponentType
is a built-in type (replaces your typeof React.Component
) and allows both class or function components to be used.
Alernative 2: Render Props
type AuthProps2 = {
childClass: (user: Maybe<User>) => JSX.Element;
};
class Auth2 extends React.Component<AuthProps2, AuthState> {
render() {
return this.props.childClass(this.state.user);
}
}
This is the preferred and safer alternative. Given the client passed an inline component like
const App = () => <Auth childClass={props => <div>{props.user}</div>} />;
, it prevents performance penalties of the first solution. Alternative 1 would remount the component in every render cycle, as the component instance changes each time (look here for a related article).
Upvotes: 1