reactjs - Randare dinamică cu React și Typescript
Folosind React cu TypeScript, încerc să redau dinamic componente în funcție de numele unui câmp
// Referencing all components
const components = {
ComponentA,
ComponentB,
};
// Dynamic render the component based on fieldName
const displayComponent = (
fieldName: keyof typeof components,
content: ComponentType
): React.ReactNode => {
const FieldNameComponent = components[fieldName];
return <FieldNameComponent item={content} />;
};
Tipurile mele:
type ComponentTypeA = {
title: string;
content: string;
};
type ComponentTypeB = {
title: string;
excerpt: string;
};
type ComponentType = ComponentTypeA | ComponentTypeB;
Compilatorul nu este mulțumit pentru că nu știe ce tip să folosească (Component1 sau Component2 care au proprietăți diferite). Primesc această eroare
Tipul 'ComponentType' nu poate fi atribuit tipului 'ComponentTypeA & ComponentTypeB'.
Tipul 'ComponentTypeA' nu poate fi atribuit tipului 'ComponentTypeB & ComponentTypeA'.
Tipul 'ComponentTypeA' nu are următoarele proprietăți din tipul 'ComponentTypeB': excerpt
Așadar, am încercat această metodă:
const displayComponent = (
fieldName: keyof typeof components,
content: ComponentType
) => {
if (content instanceof ComponentTypeA) {
return <ComponentA item={content} />;
} else if (content instanceof ComponentTypeB) {
return <ComponentB item={content} />;
}
};
Dar eroarea rămâne chiar și cu testul instanceof.
Răspuns #1
Ai putea folosi un gard de tip:
function isComponentTypeA(type: unknown): type is ComponentTypeA {
return type && "title" in type && "content" in type;
}
Și ai folosi-o în condiția:
if (isComponentTypeA(content)) {
return <ComponentA item={content} />; // inferred as ComponentTypeA
} else if (isComponentTypeB(content)) { // another type guard if needed
return <ComponentB item={content} />; // inferred as ComponentTypeB
}
Răspuns #2
Am ajuns să rezolv această eroare în felul următor:
const displayComponent = (
content: ComponentType
): React.ReactNode => {
switch (content.fieldName) {
case "ComponentA":
return <ComponentA item={ content as ComponentAType}/>
case "ComponentB":
return <ComponentB item={ content as ComponentBType}/>
default:
break;
}
};
Dar sunt destul de nefericit cu asta, pentru că dacă trebuie să mă ocup de multe componente, declarația switch va fi atât de lungă... O abordare mai bună este binevenită.
