Попытка сделать счетчик для каждого поля ввода заполнено в React с Formik - PullRequest
0 голосов
/ 21 апреля 2019

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

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

// Родительский компонент

import React, { Component } from "react";
import Formik from "./Formik";

export default class BountyPage extends Component {
state = {
total: 0
};

render() {
  return (
   <div className="bountyPage">
     <div className="total_container">
      <p className="total_title pt-2">SERV</p>
      <h1 className="total_sub">{this.state.total}</h1>
     </div>
     <Formik />
    </div>
    );
  }
 }

// Дочерний компонент

  const Formik = ({ values, errors, touched, isSubmitting, 
  setFieldValue }) => (
    <Form className="form">
    {touched.lastName &&
    values.lastName &&
     touched.firstName &&
     values.firstName ? (
       <Row>
         <Col className="result_text pulse animated p-4">
      <b>Welcome</b>{" "}
      <span
        className="clickable_text"
        onClick={async () => {
          await setFieldValue("firstName", "");
          await setFieldValue("lastName", "");
        }}
      >
        {values.firstName} {values.lastName}
      </span>
    </Col>
       </Row>
     ) : (
       <Row className="glow_form p-1">
         <Col md={6}>
           <FormGroup>
             <Label for="firstName">First Name</Label>
        <Field
          type="firstName"
          name="firstName"
          placeholder="ie. John"
          className="form-control"
        />
        {touched.firstName && errors.firstName && <p>                               
     {errors.firstName}</p>}
      </FormGroup>
    </Col>
    <Col md={6}>
      <FormGroup>
        <Label for="lastName">Last Name</Label>
        <Field
          type="lastName"
          name="lastName"
          placeholder="ie. Doe"
          className="form-control"
        />
        {touched.lastName && errors.lastName && <p> 
    {errors.lastName}</p>}
      </FormGroup>
    </Col>
  </Row>
)}
 <Row className="glow_form pt-1">
  <Col>
    <FormGroup>
      <Label for="email">Bittrex Email Address</Label>
      <Field
        type="email"
        name="email"
        placeholder="ie. example@domain.com"
        className="form-control"
      />
      {touched.email && errors.email && <p>{errors.email}</p>}
    </FormGroup>
  </Col>
  </Row>
  <Row>
  <Col className="col_container">
    <FormGroup>
      <div className="switch_container">
        <p>I’m a business owner</p>
        <label className="switch">
          <Field type="checkbox" name="switch1" checked= 
           {values.switch1} />
          <span className="slider round" />
        </label>
      </div>
    </FormGroup>
    {values.switch1 && (
      <Row className="bounceInDown animated">
        <Col md={6}>
          <FormGroup>
            <Field
              type="text"
              name="industryText"
              placeholder="ie. Automotive"
              className="form-control"
            />
          </FormGroup>
        </Col>
        <Col md={6}>
          <FormGroup>
            <Field
              type="number"
              name="locationText"
              placeholder="ie. 1-2"
              className="form-control"
            />
          </FormGroup>
        </Col>
      </Row>
    )}
  </Col>
</Row>

  {values.firstName && values.lastName ? (
   <Row>
    <Col className="text-center">
      {values.email ? (
        <span>
          <Button
            type="submit"
            disabled={isSubmitting}
            className="submit_btn"
          >
            Review
          </Button>
          <hr />
        </span>
      ) : (
        <span>
          <Button
            type="submit"
            disabled={isSubmitting}
            className="submit_btn"
          >
            Submit
          </Button>
          <hr />
        </span>
          )}
        </Col>
      </Row>
     ) : (
     ""
   )}
  </Form>
  );

 export default withFormik({
 mapPropsToValues({
 firstName,
 lastName,
 email,
 switch1,
 industryText,
 locationText,
 checkbox
  }) {
 return {
  firstName: firstName || "",
  lastName: lastName || "",
  email: email || "",
  switch1: switch1 || false,
  industryText: industryText || "",
  locationText: locationText || "",
  checkbox: checkbox || false
  };
  },
  validationSchema: Yup.object().shape({
  firstName: Yup.string()
  .max(40, "Please enter no more than 40 characters")
  .required("Please enter your first name"),
  lastName: Yup.string()
  .max(40, "Please enter no more than 40 characters")
  .required("Please enter a last name"),
   email: Yup.string()
  .email("Please enter a valid email")
  .required("Please enter an email")
   }),
   handleSubmit(values, { resetForm }) {
   console.log(values);
   resetForm();
    }
     })(Formik);

The current UI

Как мнеполучить доступ к этим «значениям» из контейнера formik в моем родительском компоненте, чтобы я мог увеличивать состояние счетчика, чтобы динамический счетчик увеличивался при каждом заполнении поля?Я пытался создать функцию обратного вызова, но не передавал ее должным образом, поскольку не знаю, как работает контейнер компонента formik.

Ответы [ 2 ]

1 голос
/ 21 апреля 2019

Только что ознакомился с документацией Formik.У них есть довольно полный пример того, что вы можете сделать здесь: https://jaredpalmer.com/formik/docs/api/field#validate

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

Родительский компонент:

import React from "react";
import Child from "./Child";

class Parent extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      counter: 0
    };
  }

  handleIncrement = event => {
    this.setState({
      counter: this.state.counter + 1
    });
  };

  handleDecrement = event => {
    this.setState({
      counter: this.state.counter - 1
    });
  };

  render() {
    return (
      <div>
        <h3>Parent Counter: {this.state.counter}</h3>
        <Child
          onComplete={this.handleIncrement}
          onInvalidate={this.handleDecrement}
        />
      </div>
    );
  }
}

export default Parent;

Дочерний компонент:

import React from "react";
import { Formik, Form, Field } from "formik";

class Child extends React.Component {
  state = {
    emailValid: false,
    passwordValid: false
  };
  //value is passed in implicitly from the Field
  validateEmail = value => {
    //insert email logic here
    if (value.includes("@") && !this.state.emailValid) {
      this.setState({
        emailValid: true
      });
      //if field is complete then increase counter on parent
      this.props.onComplete();
    } else if (!value.includes("@") && this.state.emailValid) {
      this.setState({
        emailValid: false
      });
      //if field was valid and no longer is valid
      this.props.onInvalidate();
    }
  };

  validatePassword = value => {
    //insert password logic here
    if (value.length >= 6 && !this.state.passwordValid) {
      this.setState({
        passwordValid: true
      });
      this.props.onComplete();
    } else if (value.length < 6 && this.state.passwordValid) {
      this.setState({
        passwordValid: false
      });
      //if field was valid and no longer is valid
      this.props.onInvalidate();
    }
  };

  handleSubmit = event => {
    event.preventDefault();
  };

  render() {
    return (
      <div className="app">
        <Formik
          initialValues={{ email: "", username: "" }}
          onSubmit={this.handleSubmit}
        >
          {({ errors, touched }) => (
            <Form>
              <Field validate={this.validateEmail} name="email" type="email" />
              {errors.email && touched.email ? <div>{errors.email}</div> : null}
              <Field validate={this.validatePassword} name="password" />
              {errors.password && touched.password ? (
                <div>{errors.username}</div>
              ) : null}
              <button type="submit">Submit</button>
            </Form>
          )}
        </Formik>
      </div>
    );
  }
}

export default Child;

https://codesandbox.io/s/8x736oqwq0

В конечном итоге вам придется изменить его в своей логике.Дайте мне знать, если у вас есть вопросы.:)

1 голос
/ 21 апреля 2019

Вот оно: Вы также можете перейти в эту песочницу, которую я создал:

https://codesandbox.io/s/0ovjx025lp

import React from "react";
import { render } from "react-dom";
import { Formik } from "formik";
import * as Yup from "yup";

class Parent extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      counter: 0
    };
  }
  increment = () => {
    this.setState({
      counter: this.state.counter + 1
    });
  };

  decrement = () => {
    this.setState({
      counter: this.state.counter - 1
    });
  };

  render() {
    return (
      <React.Fragment>
        <h3>Counter:: {this.state.counter}</h3>
        <App handleIncrement={this.increment} />
      </React.Fragment>
    );
  }
}

const App = originalProps => (
  <div className="app">
    <h1>
      Basic{" "}
      <a
        href="https://github.com/jaredpalmer/formik"
        target="_blank"
        rel="noopener"
      >
        Formik
      </a>{" "}
      Demo
    </h1>

    <Formik
      initialValues={{ email: "" }}
      onSubmit={(values, { setSubmitting }) => {
        setTimeout(() => {
          alert(JSON.stringify(values, null, 2));
          setSubmitting(false);
        }, 500);
      }}
      validationSchema={Yup.object().shape({
        email: Yup.string()
          .email()
          .required("Required")
      })}
    >
      {props => {
        const {
          values,
          touched,
          errors,
          dirty,
          isSubmitting,
          handleChange,
          handleBlur,
          handleSubmit,
          handleReset
        } = props;
        return (
          <form onSubmit={handleSubmit}>
            <label htmlFor="email" style={{ display: "block" }}>
              Email
            </label>
            <input
              id="email"
              placeholder="Enter your email"
              type="text"
              value={values.email}
              onChange={e => {
                originalProps.handleIncrement();
                handleChange(e);
              }}
              onBlur={handleBlur}
              className={
                errors.email && touched.email
                  ? "text-input error"
                  : "text-input"
              }
            />
            {errors.email && touched.email && (
              <div className="input-feedback">{errors.email}</div>
            )}

            <button
              type="button"
              className="outline"
              onClick={handleReset}
              disabled={!dirty || isSubmitting}
            >
              Reset
            </button>
            <button type="submit" disabled={isSubmitting}>
              Submit
            </button>
          </form>
        );
      }}
    </Formik>
  </div>
);

render(<Parent />, document.getElementById("root"));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...