Dans un composant basé sur une classe, je peux facilement écrire du code comme celui-ci:
import * as React from 'react';
import { render } from 'react-dom';
interface IProps<T> {
collapsed: boolean;
listOfData: T[];
displayData: (data: T, index: number) => React.ReactNode;
}
class CollapsableDataList<T> extends React.Component<IProps<T>> {
render () {
if (!this.props.collapsed) {
return <span>total: {this.props.listOfData.length}</span>
} else {
return (
<>
{
this.props.listOfData.map(this.props.displayData)
}
</>
)
}
}
}
render(
<CollapsableDataList
collapsed={false}
listOfData={[{a: 1, b: 2}, {a: 3, b: 4}]}
displayData={(data, index) => (<span key={index}>{data.a + data.b}</span>)}
/>,
document.getElementById('root'),
)
En fait, ce composant CollapsableDataList
devrait être un composant fonctionnel car il est sans état, mais je ne sais pas comment écrire un composant fonction et utiliser des génériques dans les accessoires, un conseil pour moi?
Vous ne pouvez pas créer un composant fonctionnel avec une annotation de type et le rendre générique. Donc cela ne fonctionnera PAS car T
n'est pas défini et vous ne pouvez pas le définir au niveau de la variable:
const CollapsableDataList : React.FunctionComponent<IProps<T>> = p => { /*...*/ }
Vous pouvez cependant ignorer l'annotation de type, rendre la fonction générique et taper props
explicitement.
import * as React from 'react';
import { render } from 'react-dom';
interface IProps<T> {
collapsed: boolean;
listOfData: T[];
displayData: (data: T, index: number) => React.ReactNode;
}
const CollapsableDataList = <T extends object>(props: IProps<T> & { children?: ReactNode }) => {
if (!props.collapsed) {
return <span>total: {props.listOfData.length}</span>
} else {
return (
<>
{
props.listOfData.map(props.displayData)
}
</>
)
}
}
render(
<CollapsableDataList
collapsed={false}
listOfData={[{a: 1, b: 2}, {a: 3, c: 4}]}
displayData={(data, index) => (<span key={index}>{data.a + (data.b || 0)}</span>)}
/>,
document.getElementById('root'),
)