I was trying to use defaultProps in functional component along with forwardRef, but was getting the error (refer screenshot).
I don't want to destructure the props in function params and assign default value. because got a lot of props in my original usecase. I also tried assigning the default values JSON directly to ComponentA.defaultProps still same result. How to resolve this ? Tried surfing but was not able to find any solution. Also since we are using TS for type check, do we still need prototype JSON ? #App.tsx
import './App.css';
import ComponentA from './components/A/A';
function App() {
return (
<div className="App">
<ComponentA>
<button>Button I am</button>
</ComponentA>
</div>
);
}
export default App;
#ComponentA.tsx
import React,{forwardRef} from "react"
import PropTypes from 'prop-types';
type Props = {
children:JSX.Element | JSX.Element[],
text:string,
text1?:string,
}
const ComponentA=(prop:Props)=>{
return <div>Hey
{prop.children}
{prop.text}
{prop.text1}
</div>
}
ComponentA.prototype = {
children:PropTypes.element.isRequired,
text:PropTypes.string.isRequired,
text1:PropTypes.string
}
ComponentA.defaultProps={
text: 'done'
} as Partial<Props>
export default forwardRef<HTMLAllCollection,Props>(ComponentA)
Thanks
CodePudding user response:
Brian Vaughn commmented on the issue of Stateless Component: React.forwardRef make defaultProps invalid
The function passed to
forwardRef
is not a React component. (React components don't accept a secondref
param for example.) It's just a function that "renders" (returns) React elements. So it does not supportdefaultProps
. We have tests that confirm this as expected behavior.React also logs the following error in the console (as can be seen in your Code Sandbox repro):
Warning: forwardRef render functions do not support propTypes or >defaultProps. Did you accidentally pass a React component?
That is the reason why you can not attach defaultProps
before passing the function that "renders"
to the forwordRef
.
It's also mentioned in the type definitions of react:
// the input of ForwardedRef
interface ForwardRefRenderFunction<T, P = {}> {
(props: P, ref: ForwardedRef<T>): ReactElement | null;
displayName?: string | undefined;
// explicit rejected with `never` required due to
// https://github.com/microsoft/TypeScript/issues/36826
/**
* defaultProps are not supported on render functions
*/
defaultProps?: never | undefined;
/**
* propTypes are not supported on render functions
*/
propTypes?: never | undefined;
}
In your case just inverse the order of declarations:
import "./styles.css";
import { forwardRef } from "react";
import PropTypes from "prop-types";
type Props = {
children: JSX.Element | JSX.Element[];
// NOTE: text is optional since he has default value.
text?: string;
text1?: string;
};
const ComponentA = forwardRef<HTMLAllCollection, Props>((prop: Props) => {
return (
<div>
Hey
{prop.children}
{prop.text}
{prop.text1}
</div>
);
});
ComponentA.prototype = {
children: PropTypes.element.isRequired,
text: PropTypes.string,
text1: PropTypes.string
};
ComponentA.defaultProps = {
text: "done"
};
export default function App() {
return (
<ComponentA>
<button>Button I am</button>
</ComponentA>
);
}