当子组件触发对父组件的状态更改时,如何防止父组件重新呈现

时间:2019-12-14 09:00:11

标签: javascript reactjs formik yup

我正在为我的前端使用react。 我有一个使用formik的注册表单,其中有以下文件-名称,电子邮件,手机,个人资料图片。 我的个人资料图片是导入到父级注册表单组件中的文件上传功能组件。 每当我上传/更改图片时,父组件都会重新渲染,这会使我失去已经填充的Formik字段值。

相反,当我从formik initialValues选项中删除profilePic时,有效的方法是

但是我想使用formik错误处理和表单提交,所以我想在formik本身中设置profilePic字段值。

在我的FileUpload功能组件中,我让用户将图像裁剪为正方形,然后将其上传到服务器并获得URL。然后,该返回的url(请参见'onDone = {this.onPicUpload}'道具)将发送回父UserDetails组件,并设置其profilePicUrl状态(请参见'onPicUpload'方法)

CodeSandbox供您快速参考:: https://codesandbox.io/s/relaxed-pond-x8bgl?fontsize=14&hidenavigation=1&theme=dark

注册表格:

import React, { Component } from 'react';
import { Formik, Form, Field, ErrorMessage } from "formik";
import * as Yup from "yup";
import PasswordInput from '../components/PasswordInput';

// form constants
const strongRegex = new RegExp("^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[!@#\$%\^&\*])(?=.{8,})"); // for Password
const phoneRegExp = /^((\\+[1-9]{1,4}[ \\-]*)|(\\([0-9]{2,3}\\)[ \\-]*)|([0-9]{2,4})[ \\-]*)*?[0-9]{3,4}?[ \\-]*[0-9]{3,4}?$/ // for Mobile Numbers
const debug = true;

class UserDetails extends Component {
  constructor(props) {
    super(props);
    this.state = {
      ...props,
      profilePicUploaded: false,
      profilePicUrl: null,
    }
    this.onPicUpload = this.onPicUpload.bind(this);
  }

  onPicUpload(url){ // imgUrl is a blob object's file value //imgUrl = blob.file
    console.log(url)
    this.setState({profilePicUrl: url})
  };

  render() {
    let _this = this;
    return(
      <div id='userDetails'>
        <p className='form-subHead'>Provide your basic details.</p>
        <Formik
          initialValues={{
            firstName: 'FirstName',
            lastName: 'LastName',
            email: 'abc@xyz.com',
            mobile: '1234567890',
            password: 'Pass@1234',
            profilePic: this.state.profilePicUrl,
          }}
          validationSchema={Yup.object().shape({
            firstName: Yup.string()
              .required('Please provide your name!')
              .min(3, 'Is that a real name?'),
            lastName: Yup.string()
              .required('Please provide your name!')
              .min(3, 'Is that a real name?'),
            email: Yup.string()
              .required("Please tell us your email.")
              .email("Please enter a valid email."),
            mobile: Yup.string()
              .required("Please tell us your mobile number.")
              .length(10, "Please enter a valid mobile number.")
              .matches(phoneRegExp, "Please enter a valid mobile number."),
            password: Yup.string()
              .required("Please enter a password.")       
              .min(8, "Password is too short - minimum 8 characters.")
              .matches(strongRegex, "Password must contain a number, a lowecase letter, a uppercase letter and a special character."),
            profilePic: Yup.mixed().required("Please upload your profile picture"),
          })}
          onSubmit={(values, { resetForm, setErrors, setSubmitting, setFieldValue }) => {
            setTimeout( () => {
              console.log("Getting form values - ", values);
              setSubmitting(false)
            }, 500);
          }}
          enableReinitialize={true}
        >

        {props => {
          const {
            values,
            touched,
            dirty,
            errors,
            isSubmitting,
            handleChange,
            setFieldValue,
            setFieldTouched
          } = props;

          return(          
            <Form noValidate >              
              <div className="row form-row">
                <div className='col-sm-6'>
                  <div className="form-group">
                    <label htmlFor="firstName" className='form-label'>First Name</label>
                    <Field
                      type='text'
                      name='firstName' placeholder='Please provide your first name'
                      className='form-control'
                    />
                    <ErrorMessage name="firstName" component="span" className="invalid-input" />
                  </div>{/* First Name */}
                </div>
                <div className='col-sm-6'>
                  <div className="form-group">
                    <label htmlFor="lastName" className='form-label'>Last Name</label>
                    <Field
                      type='text'
                      name='lastName' placeholder='Please provide your last name'
                      className='form-control'
                    />
                    <ErrorMessage name="lastName" component="span" className="invalid-input" />
                  </div>{/* Last Name */}
                </div>
              </div>
              <div className='row form-row'>
                <div className='col-sm-6'>
                  <div className="form-group">
                    <label htmlFor="email" className='form-label'>Your Email</label>
                    <Field
                      type='email'
                      name='email' placeholder='Please provide your email'
                      className='form-control'
                    />
                    <ErrorMessage name="email" component="span" className="invalid-input" />
                  </div>{/* Email */}
                </div>
                <div className='col-sm-6'>
                  <div className="form-group">
                    <label htmlFor="mobile" className='form-label'>Mobile Number</label>
                    <div className="inputGroup position-relative">
                      <span className="input-group-prepend countryCode position-absolute" id="india">+91</span>
                      <Field
                        type='number'
                        name='mobile' placeholder='Please provide your mobile Number'
                        className='form-control mobileNumber'
                      />
                    </div>                    
                    <ErrorMessage name="mobile" component="span" className="invalid-input" />
                  </div>{/* Mobile */}
                </div>
              </div>
<div className='row form-row'>
                    <div className='col-sm-6'>
<div className="form-group">
                    <label htmlFor="password" className='form-label'>Password</label>
                    <div className="inputGroup position-relative">
                      <Field
                        type='password'
                        name='mobile' placeholder='Please provide a password'
                        className='form-control password'
                      />
                    </div>                    
                    <ErrorMessage name="password" component="span" className="invalid-input" />
                  </div>{/* Password */}                
                    </div>
                    <div className='col-sm-6'>
                      <div className='form-group'>
                        <label htmlFor="profilePic" className='form-label'>Upload Profile Picture</label>
                        <FileUpload id='profilePic' name='profilePic' //setFieldValue={setFieldValue}
                          for='profileImgHolder'
                          onDone={this.onPicUpload}
                        />
                        <ErrorMessage name="profilePic" component="span" className="invalid-input" />
                        {this.state.fileUploadError && (
                          <span className='invalid-input'>{this.state.fileUploadError}</span>
                        )}
                      </div>
                    </div>
                  </div>

              <div className='text-center'>
                {isSubmitting ? <span className="loader-gif"><img src={loading} alt="Loading..." /></span> : null}
                <button type="submit" className="btn btn-filled" disabled={!dirty || isSubmitting} >       
                  Continue
                </button>
                {/*Submit */}
              </div>

              {debug && (
              <>
                <pre style={{ textAlign: "left" }}>
                  <strong>Values</strong>
                  <br />
                  {JSON.stringify(values, null, 2)}
                </pre>
                <pre style={{ textAlign: "left" }}>
                  <strong>Errors</strong>
                  <br />
                  {JSON.stringify(errors, null, 2)}
                </pre>
              </>
              )}

            </Form>
          );
        }}
        </Formik>
      </div>
    )
  }
}

export default UserDetails;




1 个答案:

答案 0 :(得分:1)

尝试将enableReinitialize设置为false。