reactjs - Comment créer un composant React fonctionnel avec un type générique ?
J'essaie de créer un composant React qui prend un paramètre de type générique qui fera partie de son type de props.
Je veux une solution qui ressemblerait à quelque chose comme ceci :
interface TestProps<T> {
value: T;
onChange: (newValue: T) => void;
}
const Test: React.FC<TestProps<T>> = (props) => (
<span>{props.value}</span>
);
J'ai vu qu'il y a un support pour cela dans TypeScript 2.9 et je suis sur la version 4.3.5.
L'utilisation de ceci ressemblerait à ceci :
const Usage: React.FC = () => (
<div>
<Test<Obj>
value={{ name: 'test' }}
onChange={(newValue) => {
console.log(newValue.name);
}}
/>
</div>
);
Sandbox de code : https://codesandbox.io/s/react-typescript-playground-forked-8hu13?file=/src/index.tsx
Réponse #1
Vous devez réécrire votre composant Test de cette manière
const Test= <T,>(props:TestProps<T>) => (
<span>Some component logic</span>
);
Pouvez-vous montrer la même chose avec React.FC<TestProps> ? Il est impossible de le faire avec
FC.
Voici l'implémentation de FC :
interface FunctionComponent<P = {}> {
(props: PropsWithChildren<P>, context?: any): ReactElement<any, any> | null;
// ... other static properties
}
Comme vous l'avez peut-être remarqué, FC est un type de fonction, pas un type de props.
MISE À JOUR
Vous pouvez créer une fonction d'ordre supérieur, mais je ne suis pas sûr que ça en vaille la peine
const WithGeneric = <T,>(): React.FC<TestProps<T>> =>
(props: TestProps<T>) => (
<span>Some component logic</span>
);
const Test = WithGeneric<Obj>()
Réponse #2
La façon la plus simple est de faire de la FC générique une fonction régulière, et non une fonction fléchée. (React.PropsWithChildren<> imite ce que React.FC fait à votre type de props.)
function Test<T>(props: React.PropsWithChildren<TestProps<T>>) {
return <span>Some component logic</span>;
}
Réponse #3
Dans mon cas, c'était comme les codes suivants :
export interface FormProps<T> {
validator?: AnyObjectSchema;
onSubmit?: (data: T) => void;
}
const Form = <T = any,>({
children,
validator,
}: PropsWithChildren<FormProps<T>>): JSX.Element => {
~~~
Et en utilisation :
type MyType = ...
<Form<MyType>
validation={something}
onSubmit={handleSomething}
>
<SomeCompo />
<AnotherSomeCompo />
</Form>
