Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React + TypeScript usage of className prop

What is the correct way to type and use the className prop in a custom component? I used to be able to do this:

class MyComponent extends React.Component<MyProps, {}> {
  ...
}

and then use my component via:

<MyComponent className="my-class" />

Note that I would not define className in MyProps, though React was previously typed to support this usage.

Now, I am now seeing this type error:

Property 'className' does not exist on type 'IntrinsicAttributes & 
IntrinsicClassAttributes<Component<{}, ComponentState>> & Readonly<{ 
childr...'

What is the correct way to define / type my component that will allow me to use className when using my component?

like image 510
mattnedrich Avatar asked Jun 05 '17 13:06

mattnedrich


People also ask

How do you pass className as props in React TypeScript?

To add the className prop to a component with React and TypeScript, we can add the React. HTMLAttributes type into our prop type. to set the prop type of MyComponent to MyProps & React. HTMLAttributes<HTMLDivElement> .

Do you need prop types with TypeScript?

Props are required in TypeScript In the prop-types package, all props are optional by default. To make a prop required, you will have to use . isRequired explicitly. With TypeScript, that is not the case.

What is the use of className in React?

In class-based components, the className attribute is used to set or return the value of an element's class attribute. Using this property, the user can change the class of an element to the desired class.


3 Answers

You can use the HTMLAttributes type, for example:

class MyComponent extends React.Component<MyProps & React.HTMLAttributes<HTMLDivElement>, {}> {
    render() {
        return <div className={ this.props.className }>My Div</div>
    }
}

That way you can pass any of the properties that a html element might need.

If you only need the className property then you can do this:

class MyComponent extends React.Component<MyProps & { className: string }, {}> {
    render() {
        return <div className={ this.props.className }>My Div</div>
    }
}

Or simply add it to your MyProps type.

like image 157
Nitzan Tomer Avatar answered Sep 28 '22 06:09

Nitzan Tomer


For someone who are looking solution for functional components, as I was.

type Props = {
  className?: string
}

const MyComponent: React.FC<Props> = (props) => (
  <div className={props.className}>{props.children}</div>
)

export default MyComponent

or if you want to declare interface separately:

interface OnlyClassNameInterface extends React.FC<{className: string}> {}

const MyComponent: OnlyClassNameInterface = (props) => (
  <div className={props.className}>{props.children}</div>
)

export default MyComponent

and you can move interface to another file

import React from 'react'

type MixProps<P> = P & {className?: string}

export interface OnlyClassNameInterface<P = {}> extends React.FC<MixProps<P> {}
like image 22
Kherel Avatar answered Sep 28 '22 04:09

Kherel


add a react-native-class-name.polyfill.d.ts

import 'react-native';
// polyfill className prop for react-native Components
declare module 'react-native' {
  interface TextProps {
    className?: string;
  }
  interface PressableProps {
    className?: string;
  }
  interface TextInputProps {
    className?: string;
  }

  interface ViewProps {
    className?: string;
  }
  interface InputAccessoryViewProps {
    className?: string;
  }

  interface ImagePropsBase {
    className?: string;
  }

  interface TouchableWithoutFeedbackProps {
    className?: string;
  }
  // others StyleProp<?> in node_modules/@types/react-native extends up show, should not define again.
}

like image 29
user12600522 Avatar answered Sep 28 '22 04:09

user12600522