简体   繁体   中英

How to extend a component to add default props in React/TS

I want to extend a component with React/TS (in my case is @mui/x-data-grid DataGrid) to fill the classes prop with my own app classes.

The way I first tought was to create a component, for example CustomDataGrid, like this:

import React from 'react';
import {DataGrid} from '@mui/x-data-grid';

const CustomDataGrid = (props) => {
  return <DataGrid {...props} classes={{root: 'my-root-class'}} />;
};

export default CustomDataGrid;

The problem is that I'm using typescript and I want to maintain the type ability to autocomplete in the IDE.

I also tried to define the type of my component as React.FC< Props>, but take a look at the DataGrid code:

declare const DataGrid: React$1.MemoExoticComponent<React$1.ForwardRefExoticComponent<Omit<Partial<DataGridPropsWithDefaultValues> & DataGridPropsWithComplexDefaultValueBeforeProcessing & DataGridPropsWithoutDefaultValue, DataGridForcedPropsKey> & {
    pagination?: true | undefined;
} & React$1.RefAttributes<HTMLDivElement>>>;

I don't know what to fill in the generic arguments to type the props.

Does anyone have an idea of how to do this without losing the autocomplete feature?

You can do that by using the React.ComponentProps ¹ utility type to get the type of the props of DataGrid , and TypeScript's Omit to remove classes from it:

import React from "react";
import {DataGrid} from "@mui/x-data-grid";

const CustomDataGrid = (props: Omit<React.ComponentProps<typeof DataGrid>, "classes">) => {
    return <DataGrid {...props} classes={{root: "my-root-class"}} />;
};

Here's a breakdown of Omit<Parameters<typeof DataGrid>[0], "classes"> :

  • typeof DataGrid gets the type of DataGrid (this is TypeScript's typeof , not JavaScript's which would just give us "function" ).
  • React.ComponentProps<...> gives us a tuple type with the types of the parameters of the function in order.
  • Omit<..., "classes"> removes the classes type from it, since you're hardcoding that and presumably don't want people to specify it when using CustomDataGrid .

Playground example

If that last bullet point isn't accurate and you do want to allow people to specify classes, you can remove the Omit<..., "classes"> part, but be sure in that case to combine any props.classes specified by the caller with your hardcoded ones; the code as it is now would override theirs with yours. For instance, something like:

const myRootClass = "my-root-class";
const CustomDataGrid = (props: React.ComponentProps<typeof DataGrid>) => {
    const classes = props.classes ?? {};
    if (classes.root) {
        classes.root += ` ${myRootClass}`;
    } else {
        classes.root = myRootClass;
    }
    return <DataGrid {...props} classes={classes} />;
};

¹ There's a note in the inline documentation of ComponentProps saying:

NOTE: prefer ComponentPropsWithRef , if the ref is forwarded, or ComponentPropsWithoutRef when refs are not supported.

...so you may want the appropriate one of those instead of ComponentProps itself.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM