Добавьте оповещение о реакции начальной загрузки для handleSubmit в Formik - PullRequest
8 голосов
/ 21 мая 2019

Я пытаюсь добавить оповещение о реакции начальной загрузки в мою форму Formik, чтобы handleSubmit включал в себя оповещение пользователю о том, что форма отправлена.

Я использовал документированную форму Alert для реакции на загрузку, однако мне пришлось изменить последнюю строку, потому что это, похоже, не работает (ошибка говорит о том, что я ничего не экспортировал, если я использую документированную форму реагирования и загрузки) предупреждение.

Мое предупреждение:

import React from 'react';

import {
    Alert,
    Button,

  } from "react-bootstrap";

class AlertDismissible extends React.Component {
    constructor(props) {
      super(props);

      this.state = { show: true };
    }

    render() {
      const handleHide = () => this.setState({ show: false });
      const handleShow = () => this.setState({ show: true });
      return (
        <>
          <Alert show={this.state.show} variant="light">
            <Alert.Heading>Thanks for your interest </Alert.Heading>
            <p>
              We'll be in touch with login details shortly.
            </p>
            <hr />
            <div className="d-flex justify-content-end">
              <Button onClick={handleHide} variant="outline-success">
                Close
              </Button>
            </div>
          </Alert>

          {!this.state.show && <Button onClick={handleShow}>Show Alert</Button>}
        </>
      );
    }
  }


export default AlertDismissible;

В документации последняя строка показана как:

render(<AlertDismissible />);

Если я попытаюсь использовать это, появится сообщение об ошибке, в котором говорится, что рендер не определен и что ничего не было экспортировано. Итак, я заменил эту строку своей последней строкой.

Тогда в моей форме я имею:

handleSubmit = (formState, { resetForm }) => {
        // Now, you're getting form state here!
        const payload = {
            ...formState,
            role: formState.role.value,
            createdAt: firebase.firestore.FieldValue.serverTimestamp()
          }
          console.log("formvalues", payload);

        fsDB
          .collection("register")
          .add(payload)
          .then(docRef => {
            resetForm(initialValues);

          })
          .then => {<AlertDismissible />}

          .catch(error => {
            console.error("Error adding document: ", error);
          });
    }

На самом деле я не знаю, как заставить работать оповещение (приведенное выше утверждение - это предположение - я не могу найти никаких примеров. Это предположение дает ошибку, которая говорит:

Parsing error: Unexpected token, expected ";"

Я пытался добавить ";" в любом месте я могу подумать, чтобы поставить один, но он продолжает генерировать ошибки.

Если я попробую это так:

.then(<AlertDismissible />)

Я не получаю ошибок, и форма отправляется, но предупреждение не отображается.

Кто-нибудь знает, как вызвать оповещение о реакции начальной загрузки в функции отправки дескриптора?

Кнопка отправки имеет:

<Button
  variant="outline-primary"
  type="submit"
  style={style3}
  id="submitRegistration"
  onClick={handleSubmit}
  disabled={!dirty || isSubmitting}>
   Register
</Button>

OnSubmit имеет:

onSubmit={
  this.handleSubmit
}

Вся моя форма выглядит так:

import React from 'react';
import { Link } from "react-router-dom";
import { Formik, Form, Field, ErrorMessage, withFormik } from "formik";
import * as Yup from "yup";
import Select from "react-select";
import { fsDB, firebase, settings } from "../../firebase";
import Temporarynav from '../navigation/Temporarynav.jsx';
import Demo from '../landing/Demo.jsx';
import Footer from '../footer/Footer.jsx';
import "./preregister/Form.css";
import AlertDismissible from '../auth/preregister/Alert';


import {
    Badge,
    Button,
    Col,
    ComponentClass,
    Feedback,
    FormControl,
    FormGroup,
    Table,
    Row,
    Container
  } from "react-bootstrap";
import Alert from 'react-bootstrap/Alert';

  const style1 = {
    width: "60%",
    margin: "auto"
  };

  const style2 = {
    paddingTop: "2em"
  };

  const style3 = {
    marginRight: "2em"
  };



const initialValues = {
firstName: "",
lastName: "",
email: "",
role: "",
consent: false,
createdAt: ''
}


class PreregForm extends React.Component {

    // constructor(props) {
    //   super(props);

    //   // the flag isFormDone will control where you will show the Alert component
    //   this.state = {
    //     isFormDone: false
    //   };
    // }
    handleSubmit = (formState, { resetForm }) => {
        // Now, you're getting form state here!
        const payload = {
            ...formState,
            role: formState.role.value,
            createdAt: firebase.firestore.FieldValue.serverTimestamp()
          }
          console.log("formvalues", payload);

        fsDB
          .collection("preregistrations")
          .add(payload)
          .then(docRef => {
            resetForm(initialValues);

          })
          .then(() => {
            // Here is where you flag your form completion and allow the alert to be shown.
            // this.setState((prevState) => {...prevState, isFormDone: true});
          .catch(error => {
            console.error("Error adding document: ", error);
          });
    }

    render() {
        const options = [
            { value: "academic", label: "Academic Researcher" },
            { value: "student", label: "Student (inc PhD)" },
        ] 

        // const {isFormDone} = this.state;

        return(
            <Formik
                initialValues={initialValues}
                validationSchema={Yup.object().shape({
                    firstName: Yup.string().required("First Name is required"),
                    lastName: Yup.string().required("Last Name is required"),
                    email: Yup.string()
                        .email("Email is invalid")
                        .required("Email is required"),
                    role: Yup.string().nullable().required(
                        "It will help us get started if we know a little about your background"
                    ),
                    consent: Yup.boolean().oneOf(
                        [true],
                        "You must accept the Terms of Use and Privacy Policy"
                    )
                })}  
                onSubmit={
                  this.handleSubmit
                }
                render={({ 
                    errors, 
                    status, 
                    touched, 
                    setFieldValue,
                    setFieldTouched, 
                    handleSubmit, 
                    isSubmitting, 
                    dirty, 
                    values 
                }) => {

                  return (
                    <div>  
                    <Temporarynav />  
                    <Form style={style1}>
                      <h1 style={style2}>Get Started</h1>
                      <p>
                        We're almost ready to open this up to the research community. By
                        registering now, you'll be first in line when the doors open.
                      </p>
                      <div className="form-group">
                        <label htmlFor="firstName">First Name</label>
                        <Field
                          name="firstName"
                          type="text"
                          className={
                            "form-control" +
                            (errors.firstName && touched.firstName ? " is-invalid" : "")
                          }
                        />
                        <ErrorMessage
                          name="firstName"
                          component="div"
                          className="invalid-feedback"
                        />
                      </div>
                      <div className="form-group">
                        <label htmlFor="lastName">Last Name</label>
                        <Field
                          name="lastName"
                          type="text"
                          className={
                            "form-control" +
                            (errors.lastName && touched.lastName ? " is-invalid" : "")
                          }
                        />
                        <ErrorMessage
                          name="lastName"
                          component="div"
                          className="invalid-feedback"
                        />
                      </div>
                      <div className="form-group">
                        <label htmlFor="email">Email</label>
                        <Field
                          name="email"
                          type="text"
                          placeholder="Please use your work email address"
                          className={
                            "form-control" +
                            (errors.email && touched.email ? " is-invalid" : "")
                          }
                        />
                        <ErrorMessage
                          name="email"
                          component="div"
                          className="invalid-feedback"
                        />
                      </div>
                      <div className="form-group">
                        <label htmlFor="role">
                        Which role best describes yours?
                        </label>

                        <Select
                        key={`my_unique_select_keyrole`}
                        name="role"
                        className={
                            "react-select-container" +
                            (errors.role && touched.role ? " is-invalid" : "")
                        }
                        classNamePrefix="react-select"
                        value={values.role}
                        onChange={selectedOptions => {
                            // Setting field value - name of the field and values chosen.
                            setFieldValue("role", selectedOptions)}
                            }
                        onBlur={setFieldTouched}
                        options={options}
                        />
                        {errors.role && touched.role && 
                        <ErrorMessage
                        name="role"
                        component="div"
                        className="invalid-feedback d-block"
                        />}
                      </div>


                      <div className="form-group">
                        <div className="checkbox-wrapper">
                            <Field
                              name="consent"
                              type="checkbox"
                              checked={values.consent}
                              className={
                                "checkbox" +
                                (errors.consent && touched.consent ? " is-invalid" : "")
                              }
                            />
                        <label htmlFor="consent" className="checkbox_label_wrapper">
                          You must accept the{" "}
                          <Link className="links" to={"/Terms"}>
                            Terms of Use
                          </Link>{" "}
                          and{" "}
                          <Link className="links" to={"/Privacy"}>
                            Privacy Policy
                          </Link>


                        </label>
                        </div>

                        {errors.consent && touched.consent && 
                        <ErrorMessage
                          name="consent"
                          component="div"
                          className="invalid-feedback d-block"
                        />
                        }
                      </div>


                      <div className="form-group">
                        <Button
                          variant="outline-primary"
                          type="submit"
                          style={style3}
                          id="submitRegistration"
                          onClick={handleSubmit}
                          disabled={!dirty || isSubmitting}

                          >
                          Register
                        </Button>
                      </div>
                    </Form>
                    <Demo />
                    <Footer />
                    </div>


                  );
                }
                } 
            /> 
        )    

    }
}            

export default PreregForm;

Следующая попытка

Когда я пытаюсь использовать решение Julius, появляется предупреждение, но как нижний колонтитул под формой, а не как всплывающее предупреждение.

Ответы [ 2 ]

3 голосов
/ 23 мая 2019

Использовать государственный и условный рендеринг.Вместо того, чтобы возвращать состояние набора компонентов в переменную, в вашем рендере используйте условный рендеринг, чтобы проверить, является ли значение истинным.

handleSubmit = (formState, { resetForm }) => {
  // Now, you're getting form state here!
  const payload = {
    ...formState,
    role: formState.role.value,
    createdAt: firebase.firestore.FieldValue.serverTimestamp()
  };
  console.log('formvalues', payload);

  fsDB
    .collection('register')
    .add(payload)
    .then(docRef => {
      resetForm(initialValues);
    })
    .then(e => this.setState({ alert: true }))

    .catch(error => {
      console.error('Error adding document: ', error);
    });
};

В вашем рендере

render() {
 ...
  return(
 ....
   {this.state.alert && <AlertDismissible />}
 ...
  )
}

ПримерДемоверсия

Полная форма

import React from 'react';
import { Link } from 'react-router-dom';
import { Formik, Form, Field, ErrorMessage, withFormik } from 'formik';
import * as Yup from 'yup';
import Select from 'react-select';
import { fsDB, firebase, settings } from '../../firebase';
import Temporarynav from '../navigation/Temporarynav.jsx';
import Demo from '../landing/Demo.jsx';
import Footer from '../footer/Footer.jsx';
import './preregister/Form.css';
import AlertDismissible from '../auth/preregister/Alert';

import {
  Badge,
  Button,
  Col,
  ComponentClass,
  Feedback,
  FormControl,
  FormGroup,
  Table,
  Row,
  Container
} from 'react-bootstrap';
import Alert from 'react-bootstrap/Alert';

const style1 = {
  width: '60%',
  margin: 'auto'
};

const style2 = {
  paddingTop: '2em'
};

const style3 = {
  marginRight: '2em'
};

const initialValues = {
  firstName: '',
  lastName: '',
  email: '',
  role: '',
  consent: false,
  createdAt: ''
};

class PreregForm extends React.Component {
  constructor(props) {
    super(props);

    // the flag isFormDone will control where you will show the Alert component
    this.state = {
      showAlert: false
    };
  }
  handleSubmit = (formState, { resetForm }) => {
    // Now, you're getting form state here!
    const payload = {
      ...formState,
      role: formState.role.value,
      createdAt: firebase.firestore.FieldValue.serverTimestamp()
    };
    console.log('formvalues', payload);

    fsDB
      .collection('preregistrations')
      .add(payload)
      .then(docRef => {
        resetForm(initialValues);
      })
      .then(e => this.setState({ showAlert: true }))
      .catch(error => {
        console.error('Error adding document: ', error);
      });
  };

  render() {
    const options = [
      { value: 'academic', label: 'Academic Researcher' },
      { value: 'student', label: 'Student (inc PhD)' }
    ];

    // const {isFormDone} = this.state;

    return (
      <div>
        {!this.state.showAlert ? (
          <div>
            <Formik
              initialValues={initialValues}
              validationSchema={Yup.object().shape({
                firstName: Yup.string().required('First Name is required'),
                lastName: Yup.string().required('Last Name is required'),
                email: Yup.string()
                  .email('Email is invalid')
                  .required('Email is required'),
                role: Yup.string()
                  .nullable()
                  .required(
                    'It will help us get started if we know a little about your background'
                  ),
                consent: Yup.boolean().oneOf(
                  [true],
                  'You must accept the Terms of Use and Privacy Policy'
                )
              })}
              onSubmit={this.handleSubmit}
              render={({
                errors,
                status,
                touched,
                setFieldValue,
                setFieldTouched,
                handleSubmit,
                isSubmitting,
                dirty,
                values
              }) => {
                return (
                  <div>
                    <Temporarynav />
                    <Form style={style1}>
                      <h1 style={style2}>Get Started</h1>
                      <p>
                        We're almost ready to open this up to the research
                        community. By registering now, you'll be first in line
                        when the doors open.
                      </p>
                      <div className="form-group">
                        <label htmlFor="firstName">First Name</label>
                        <Field
                          name="firstName"
                          type="text"
                          className={
                            'form-control' +
                            (errors.firstName && touched.firstName
                              ? ' is-invalid'
                              : '')
                          }
                        />
                        <ErrorMessage
                          name="firstName"
                          component="div"
                          className="invalid-feedback"
                        />
                      </div>
                      <div className="form-group">
                        <label htmlFor="lastName">Last Name</label>
                        <Field
                          name="lastName"
                          type="text"
                          className={
                            'form-control' +
                            (errors.lastName && touched.lastName
                              ? ' is-invalid'
                              : '')
                          }
                        />
                        <ErrorMessage
                          name="lastName"
                          component="div"
                          className="invalid-feedback"
                        />
                      </div>
                      <div className="form-group">
                        <label htmlFor="email">Email</label>
                        <Field
                          name="email"
                          type="text"
                          placeholder="Please use your work email address"
                          className={
                            'form-control' +
                            (errors.email && touched.email ? ' is-invalid' : '')
                          }
                        />
                        <ErrorMessage
                          name="email"
                          component="div"
                          className="invalid-feedback"
                        />
                      </div>
                      <div className="form-group">
                        <label htmlFor="role">
                          Which role best describes yours?
                        </label>

                        <Select
                          key={`my_unique_select_keyrole`}
                          name="role"
                          className={
                            'react-select-container' +
                            (errors.role && touched.role ? ' is-invalid' : '')
                          }
                          classNamePrefix="react-select"
                          value={values.role}
                          onChange={selectedOptions => {
                            // Setting field value - name of the field and values chosen.
                            setFieldValue('role', selectedOptions);
                          }}
                          onBlur={setFieldTouched}
                          options={options}
                        />
                        {errors.role && touched.role && (
                          <ErrorMessage
                            name="role"
                            component="div"
                            className="invalid-feedback d-block"
                          />
                        )}
                      </div>

                      <div className="form-group">
                        <div className="checkbox-wrapper">
                          <Field
                            name="consent"
                            type="checkbox"
                            checked={values.consent}
                            className={
                              'checkbox' +
                              (errors.consent && touched.consent
                                ? ' is-invalid'
                                : '')
                            }
                          />
                          <label
                            htmlFor="consent"
                            className="checkbox_label_wrapper"
                          >
                            You must accept the{' '}
                            <Link className="links" to={'/Terms'}>
                              Terms of Use
                            </Link>{' '}
                            and{' '}
                            <Link className="links" to={'/Privacy'}>
                              Privacy Policy
                            </Link>
                          </label>
                        </div>

                        {errors.consent && touched.consent && (
                          <ErrorMessage
                            name="consent"
                            component="div"
                            className="invalid-feedback d-block"
                          />
                        )}
                      </div>

                      <div className="form-group">
                        <Button
                          variant="outline-primary"
                          type="submit"
                          style={style3}
                          id="submitRegistration"
                          onClick={handleSubmit}
                          disabled={!dirty || isSubmitting}
                        >
                          Register
                        </Button>
                      </div>
                    </Form>
                    <Demo />
                    <Footer />
                  </div>
                );
              }}
            />
          </div>
        ) : (
          <AlertDismissible />
        )}
      </div>
    );
  }
}

export default PreregForm;
0 голосов
/ 23 мая 2019

Вы не можете вернуть такой компонент в функции then. Вы должны управлять флагом состояния, который показывает предупреждение, основанное на заполнении формы.

Возможно, вы могли бы поделиться всем своим компонентом, где вы обрабатываете submit, показанный здесь, чтобы мы могли оказать вам дополнительную помощь (обновим ответ, если вы обновите вопрос).

Но я думаю, что это будет что-то вроде следующего:

class MyFormComponent extends React.Component {

  constructor(props) {
    super(props);

    // the flag isFormDone will control where you will show the Alert component
    this.state = {
      isFormDone: false
    };
  }

  /** Here your form handling as you posted */
  handleSubmit = (formState, { resetForm }) => {
      const payload = {
          ...formState,
          role: formState.role.value,
          createdAt: firebase.firestore.FieldValue.serverTimestamp()
        }
        console.log("formvalues", payload);

      fsDB
        .collection("register")
        .add(payload)
        .then(docRef => {
          resetForm(initialValues);

        })
        .then(() => {
          // Here is where you flag your form completion and allow the alert to be shown.
          this.setState((prevState) => ({...prevState, isFormDone: true}));
        })
        .catch(error => {
          console.error("Error adding document: ", error);
        });
  }


  render() {

    const {isFormDone} = this.state;

    // this will only render the Alert when you complete your form submission
    const alert = isFormDone ? <AlertDismissible/> : null;

    return(
      {/* syntax sugar for React Fragment */}
      <> 
        {/* if it is null, it won't render anything */}
        {alert}

        {/* Your Form here with your handler */}
        {/* ... */}
      </>
      );

  }

}
...