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

Javascript 当子组件触发对父组件的状态更改时,如何防止父组件重新渲染,javascript,reactjs,formik,yup,Javascript,Reactjs,Formik,Yup,我用react作为前端。 我有一个使用formik的注册表格,它有以下文件-姓名、电子邮件、手机、个人资料图片。 我的个人资料图片是一个文件上传功能组件,导入到父注册表单组件中。 每当我上传/更改图片时,父组件都会重新加载,这会导致我丢失已填充的formik字段值 取而代之的是,当我从FormikInitialValues选项中删除profilePic时 但我想使用formik错误处理和表单提交,所以我想在formik本身中设置profilePic字段值 在我的FileUpload功能组件中,我

我用react作为前端。 我有一个使用formik的注册表格,它有以下文件-姓名、电子邮件、手机、个人资料图片。 我的个人资料图片是一个文件上传功能组件,导入到父注册表单组件中。 每当我上传/更改图片时,父组件都会重新加载,这会导致我丢失已填充的formik字段值

取而代之的是,当我从FormikInitialValues选项中删除profilePic时

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

在我的FileUpload功能组件中,我让用户将图像裁剪成方形,然后将其上载到服务器并获取url。然后将返回的url(请参阅'onDone={This.onPicUpload}'props)发送回父UserDetails组件,并设置其profilePicUrl状态(请参阅'onPicUpload'方法)

代码沙盒供您快速参考::

报名表格:

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;




import React,{Component}来自'React';
从“Formik”导入{Formik,Form,Field,ErrorMessage};
从“Yup”导入*作为Yup;
从“../components/PasswordInput”导入PasswordInput;
//形式常数
常量strongRegex=newregexp(“^(?=.[a-z])(?=.[a-z])(?=.[0-9])(?=.[!@\$%\^&*])(?=.{8,}]);/密码
const phoneRegExp=/^(\+[1-9]{1,4}[\-]*)(\\([0-9]{2,3}\\\)[\-]*)([0-9]{2,4}[\-]*)*?[0-9]{3,4}.[\-]*[0-9]{3,4}$///手机号码
const debug=true;
类UserDetails扩展组件{
建造师(道具){
超级(道具);
此.state={
…道具,
错误:错误,
profilePicUrl:null,
}
this.onPicUpload=this.onPicUpload.bind(this);
}
onPicUpload(url){//imgUrl是blob对象的文件值//imgUrl=blob.file
console.log(url)
this.setState({profilePicUrl:url})
};
render(){
让_this=this;
返回(

提供您的基本细节

{ 设置超时(()=>{ log(“获取表单值-”,值); 设置提交(错误) }, 500); }} enableReinitialize={true} > {props=>{ 常数{ 价值观 感动的, 肮脏的, 错误, 提交, handleChange, setFieldValue, Setfieldtouch }=道具; 报税表( 名字 {/*名字*/} 姓 {/*姓氏*/} 你的电子邮件 {/*电子邮件*/} 手机号码 +91 {/*Mobile*/} 密码 {/*密码*/} 上传个人资料图片 {this.state.fileUploadError&&( {this.state.fileUploadError} )} {isSubmitting?:null} 继续 {/*提交*/} {调试&&(
{JSON.stringify(值,null,2)} 错误
{JSON.stringify(错误,null,2)} )} ); }} ) } } 导出默认用户详细信息;
尝试将enableReinitialize设置为false。

尝试将enableReinitialize设置为false