web-dev-qa-db-fra.com

Passez des accessoires personnalisés au champ de formulaire Redux dans TypeScript

Je veux transmettre des propriétés personnalisées à mon champ de formulaire Redux. Dans la documentation, il est écrit:

Tous les accessoires personnalisés transmis à Field seront fusionnés dans l'objet d'accessoires au même niveau que les objets d'entrée et méta.

Mais en passant un accessoire personnalisé au composant Field, une erreur de compilation sera générée:

<Field
    name="E-Mail"
    component={MaterialTextField}
    myProp="Test"
/>

La propriété 'myProp' n'existe pas sur le type '(IntrinsicAttributes & IntrinsicClassAttributes> & ...

À l'intérieur de l'attribut props, je ne peux ajouter qu'un ensemble prédéfini de propriétés comme un espace réservé ou un type. Passer un autre accessoire provoquera cette erreur:

<Field
    name="E-Mail"
    component={MaterialTextField}
    props = {{
        myProps: 'Test'
    }}
/>

Tapez '{nom: "E-Mail"; composant: (props: any) => Element; props: {myProps: string; }; } 'n'est pas assignable au type' (IntrinsicAttributes & ...

Existe-t-il une possibilité de passer des accessoires personnalisés au composant Field dans TypeScript?

16
Deutro

Après quelques essais supplémentaires de mon côté, j'ai trouvé une solution pour passer des accessoires personnalisés:

<Field 
    name="myName"
    props={{
        type: 'text'
    }}
    component={myComponent}
    {...{
        myCustomProps1: 'myCustomProp1',
        myCustomProps2: 'myCustomProp2'
    }}
/>

Dans myComponent, vous avez vos accessoires personnalisés au niveau racine de vos propriétés:

const myComponent = (props) => {
    return <div>{props.myCustomProp1 + " " props.myCustomProp2}</div>
}
16
Deutro

Pour passer accessoires personnalisés au composant Field de Formulaire Redux, vous devez déclarer un interface de tous les accessoires vous voulez passer.

interface YourCustomProps {
    myProp1: string;
    myProp2: number;
}

Maintenant, utilisez GenericField de Formulaire Redux pour faire Field comme YourCustomField auquel vous pourrez passer YourCustomProps

import { Field, GenericField } from 'redux-form';

const YourCustomField = Field as new () => GenericField<YourCustomProps>;

Vous pouvez maintenant passer accessoires personnalisés à YourCustomField comme déclaré dans l'interface.

<YourCustomField
    myProp1="Hi"
    myProp2={123}
    component={MaterialTextField}
/>

De cette façon, vous pouvez passer n'importe quoi accessoires personnalisés tels que les composants réactifs! :)

1
Vinay Sharma

Je ne suis pas un utilisateur TypeScript, donc je ne sais pas comment fonctionnent les définitions de type, mais j'ai trouvé ce fil sur les définitions de type pour Redux-form v6 . À la fin, ils sont liés à ce référentiel qui est censé avoir (si je comprends bien) des définitions de type mises à jour.

Je suppose qu'une alternative serait de passer à Vanilla JS pour cette fonctionnalité spécifique. Ou peut-être qu'il serait possible de définir une fonction qui prend votre accessoire personnalisé puis retourne un composant prêt à prendre les accessoires de formulaire Redux et à les fusionner.

Edit : J'ai essayé d'illustrer l'idée de base de la dernière suggestion, un soi-disant HOC (Higher Order Component), dans le code inclus ci-dessous .

const inputWithCustomFields = (customFields) => ComponentToGetExtraFields => (props) => {
        const mergedProps = {...props, ...customFields};
        return (<ComponentToGetExtraFields {...mergedProps} />);
};

const ComponentThatNeedsCustomStuff = ({myCustomField1, myCustomField2, ...rest}) => {
        console.log('doing stuff with the custom props',myCustomField1, myCustomField2);
        return (<div><h1>{myCustomField1 + myCustomField2}</h1><input {...rest} /></div>);
}

const Parent = () => {
  const myCustomFields = {
     myCustomField1: "Hello, ", 
     myCustomField2: "world!", 
     value: 'can\'t change me',
     onChange: () => { /* do nothing */ }
   };
  const MergedComponent  = inputWithCustomFields(myCustomFields)(ComponentThatNeedsCustomStuff);
  return (<div>
      <MergedComponent />
    </div>);
};

ReactDOM.render(<Parent />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>
0
jonahe