2 votes

React JS - Composer un formulaire générique avec des enfants dynamiques

Je suis un débutant en reactjs. Je me sens très bien à l'idée de l'utiliser, mais je suis bloqué depuis un moment sur un concept que je veux mettre en œuvre, qui résoudrait tout un tas d'autres problèmes.

Concept

  • Je souhaite créer un composant de formulaire qui peut recevoir des enfants dynamiques. Il ne s'agira pas d'un composant de formulaire spécifique comme Formulaire de connexion, Formulaire de contact etc. Il s'agirait plutôt de Formulaire .

Approche 1

class LoginPage extends Rect.Component {

    constructor(props) {
        super(props)

        this.submit = this.submit.bind(this);
        this.validate = this.validate.bind(this);
        this.reset = this.reset.bind(this);
    }

    submit(...args) {
        this.refs.form.submit(args);
    }

    validate(...args) {
        this.refs.form.validate(args);
    }

    reset(...args) {
        this.refs.form.reset(args);
    }

    render() {
        return (
        <LoginPage>
            <Form ref="form" onSubmit={this.submit}>
                <Input value="email" pattern="/email_pattern/" onValidate={this.validate} />

                <Input value="password" pattern="/password_pattern/" onValidate={this.validate} />

                <Button value="submit" action={this.submit} />
                <Button value="reset" action={this.reset} />
            </Form>
        </LoginPage>
    }
}
  • Input onChange appelle la fonction validate qui transmet simplement les arguments à la fonction validate du formulaire. Pour que le formulaire sache si tous ses enfants sont validés. Je passe isValid et targetInputComponent comme arguments au formulaire.
  • Le bouton Submit onClick appelle la fonction submit de la même manière et LoginPage (qui joue le rôle d'intergiciel) transmet l'appel au composant Form. Le formulaire vérifie l'état des entrées inValid, etc.
  • L'appel onClick de la réinitialisation du bouton est transmis au composant Form de la même manière. Mais comment le formulaire gère-t-il cette fonctionnalité de réinitialisation ? La valeur de l'entrée est contrôlée par la page de connexion. Le formulaire ne peut pas modifier la valeur de l'entrée.

Approche 2

Ce que j'ai fait, c'est ajouter les données et la validité de l'entrée à l'état de la page de connexion. Désormais, les composants Form et Inputs appellent simplement la page de connexion pour mettre à jour son état. Les composants Form et Inputs utilisent cet état comme prop.

class LoginPage extends React.Component {

    constructor(props) {
        super(props)

        this.state = {
            formSchema: this.initSchema()
        }

        this.validateField = this.validateField.bind(this);
        this.submitForm = this.submitForm.bind(this);
    }

    initSchema() {
        const formSchema = {
            email: {
                isValid: false,
                value: ''
            },
            password: {
                isValid: false,
                value: ''
            },
            password2: {
                isValid: false,
                value: ''
            }
        }

        return formSchema;
    }

    validateField(dataObj, targetComponent) {

        const formSchema = Object.assign(this.state.formSchema, dataObj);

        this.setState({ formSchema })
    }

    submitForm(isSuccess) {
        console.log(isSuccess);
        console.log('Form Submit: ', this.state.formSchema);

        throw new Error('Submition Error');
    }

    reset() {
        // Loop through each object in formSchema and set it's value to empty, inputs will validate themselves automatically.
    }

    render() {
        return <div>
            <Form ref="formLogin" className="auth-form" onSubmit={this.submitForm} formSchema={this.state.formSchema}>
                <h1>
                    Switch Accounts
                </h1>
                <Input type="email" name="email" onValidate={this.validateField} value={this.state.formSchema.email.value}
                isValid={this.state.formSchema.email.isValid}/>

                <Input type="password" name="password" onValidate={this.validateField} value={this.state.formSchema.password.value}
                isValid={this.state.formSchema.password.isValid}/>

                <Button value="Submit" type="submit"  />
            </Form>
        </div>
    }
}

Problème

Cette approche rend le composant LoginPage assez désordonné. Comment le composant LoginPage va-t-il gérer les formulaires si j'ai plus d'un formulaire sur la page ? Il y aura encore plus de fonctionnalités dans la LoginPage, comme les listes, les grilles, les fenêtres modales, etc. Cette page de connexion ne devrait pas gérer ces situations. Formulaire devrait être responsable de toutes les fonctionnalités d'entrée, de soumission, etc. Ce composant de formulaire doit être générique pour tous les types de formulaires. Je ne veux pas créer des formulaires de type LoginForm, ContactForm, etc.

La solution à cette question me sera d'une grande aide dans bien d'autres domaines.

1voto

pscl Points 1702

Votre approche 2 est la manière standard de traiter ce problème.

Pourquoi ne pas créer un <LoginForm> ? Cela permet d'isoler les champs et la validation des autres fonctionnalités non liées de votre page.

Si, plus tard, vous avez besoin d'un <ContactForm> ou tout autre type de formulaire, il aura différents champs et différentes logiques de validation, ce qui signifie que vous devrez le construire de toute façon.

À moins d'utiliser quelque chose comme redux vous êtes sur la bonne voie.

1voto

Giovanni Points 155

Il existe de nombreuses façons de créer des formulaires "génériques". Mais à mon avis, il est préférable de conserver les formulaires séparément.

La raison pour laquelle je dis cela, c'est que d'une manière ou d'une autre, vous devez toujours mettre en œuvre diverses conditions de validation pour la plupart des champs, tels que l'adresse électronique ou tout autre champ que vous utiliserez.

Je pense que la meilleure approche consiste à individualiser les composants. Par exemple : créer un composant TextField qui gère les entrées comme la validation. Peut-être un composant Button pour la soumission et les rappels.

Mon conseil est donc le suivant : séparez les formulaires. Inutile de trop réfléchir et de perdre du temps en essayant de rendre les choses "jolies".

Bonne chance !

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X