0

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?

1 Answer 1

1

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).

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.