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?
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> .
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.
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.
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.
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> {}
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.
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With