Home > Blockchain >  How to set a type for a React Compnent being passed in as a prop
How to set a type for a React Compnent being passed in as a prop

Time:10-27

I have the following code where I'm rendering a component or redirecting the user based on auth state. I'm having trouble understanding what the component prop type should be set to in the interface I've declared:

import { useState } from 'react';
import { Redirect, Route } from 'react-router-dom';
import { useAuthState } from '../../../context/authenticationContext';

interface AppProps {
    path: string,
    isPrivate: boolean,
}

const AppRoutes = ({ component: Component, path, isPrivate, ...rest }: AppProps) => {
    const authDetails = useAuthState();
    ...
    return (
        <Route
            path={path}
            render={props => (isPrivate && !authDetails.user) ? (
                <Redirect
                    to={{ pathname: "/" }}
                />
            ) : (
                <Component {...props} />
            )
            }
            {...rest}
        />
    )
}

export default AppRoutes

As you can see my interface is missing the component type. Not sure what to set it to.

CodePudding user response:

If you want to type component constructor you should use import {ComponentType} from 'react'.

So, if you want to build Component with props from render function, you should apply a constraint for ComponentTypeProps.

In other words, your Component should expect Route['render'] type of argument. In order to get type of render argument, you should use ComponentProps utility, which you can import from 'react'.

COnsider this example:

type RenderProps = Parameters<NonNullable<ComponentProps<typeof Route>['render']>>[0]

Now you can use appropriate constraint:

import React, { ComponentType, ComponentProps } from 'react';
import { Route } from 'react-router-dom';

interface AppProps {
  path: string,
  isPrivate: boolean,
  Component: ComponentType<RenderProps>
}

type RenderProps = Parameters<NonNullable<ComponentProps<typeof Route>['render']>>[0]

const AppRoutes = ({ Component, path, isPrivate, ...rest }: AppProps) => {

  return (
    <Route
      path={path}
      render={props => <Component {...props} />}
      {...rest}
    />
  )
}

export default AppRoutes

Playground

  • Related