Redux窗体,按键后失去焦点?

kkbh8khc  于 2023-04-06  发布在  其他
关注(0)|答案(1)|浏览(107)

我遇到了一个奇怪的问题。我有一个表单,在那里我有一个输入字段,但是在我用按键触发onChange事件后,它失去了输入字段的焦点。

{editPhoneEnabled && <Field
        name="phoneNumber"
        component={phoneFieldRenderer}
        validate={[Validator.required, Validator.phone]}
      />}

const phoneFieldRenderer = ({ input }) => {
  return (
    <ReactTelInput {...input} />
  )
}

我已经看到了这个例子的问题发生的设置(https://codepen.io/invisiblecomma/pen/wqLaZQ),但我已经做了类似的,你可以看到,但它仍然不工作?
有什么想法可以帮助我了解发生了什么事?
整个组件:

import React, { useState, useEffect } from 'react';
import { Field, reduxForm, getFormValues } from 'redux-form';
import { Col, FormGroup } from 'reactstrap';
import { t } from 'Utilities/i18n';
import Validator from 'Utilities/validation';
import Button from 'Components/Forms/Button';
import { connect } from 'react-redux';
import { gql, useMutation } from '@apollo/client';
import ReactTelInput from 'react-telephone-input';

const formName = 'PhoneVerifyForm';

const performPhoneVerificationMutation = gql`
  mutation registerPage_userPhoneVerification($input: RegisterPhoneVerificationInput!) {
    userPhoneVerification(input: $input) {
      errors {
        field
        messages
      }
      phoneNumberVerificationSid
      verified
    }
  }
`;

// TODO props: unconfirmedUserId, phoneNumberVerificationSid, initialValues, callback
const PhoneVerifyForm = (props) => {
  const [editPhoneEnabled, setEditPhoneEnabled] = useState(false);
  const [codeSend, setCodeSend] = useState(props.phoneNumberVerificationSid !== undefined);
  const [performPhoneVerification, { data:performPhoneVerificationData }] = useMutation(performPhoneVerificationMutation);
  const [errors, setErrors] = useState([]);

  useEffect(() => {
    if (performPhoneVerificationData && performPhoneVerificationData.userPhoneVerification) {
      const {userPhoneVerification} = performPhoneVerificationData;

      if(userPhoneVerification.errors.length === 0) {
        setErrors([])
        if (editPhoneEnabled) {
          editPhoneEnabled(false);
        }

        setCodeSend(userPhoneVerification.phoneNumberVerificationSid !== undefined);

        if(userPhoneVerification.verified !== undefined) {
          props.callback(props.formValues.phone);
        }
      } else {
        setErrors(userPhoneVerification.errors)
      }
    }
  }, [performPhoneVerificationData, ])

  function handleSubmit(values) {
    if (editPhoneEnabled) {
      // update phone number
      return performPhoneVerification({
        variables: {
          input: {
            unconfirmedUserId: props.unconfirmedUserId,
            phone: values.phoneNumber,
          },
        },
      });
    } else if (!codeSend) {
      // send new code
      return performPhoneVerification({
        variables: {
          input: {
            unconfirmedUserId: props.unconfirmedUserId,
            channel: values.channel,
          },
        },
      });
    }
    // else validate code
    return performPhoneVerification({
      variables: {
        input: {
          unconfirmedUserId: props.unconfirmedUserId,
          code: values.code,
        },
      },
    });
  }

  const handleEditPhone = () => {
    setEditPhoneEnabled(!editPhoneEnabled);
    setCodeSend(false);
  };

  const phoneFieldRenderer = ({ input }) => {
    return (
      <ReactTelInput {...input} />
    )
  }

  return (
    <form className="row" onSubmit={props.handleSubmit(handleSubmit)}>
      {!codeSend && <Col style={{background: 'pink'}}>
        <p>{t('select channel')}</p>
        <FormGroup row className="indented-form-group">
          <Col>
            <label>
              <Field
                name="channel"
                component="input"
                type="radio"
                value="sms"
                validate={Validator.required}
              />
              {t('Sms')}
            </label>
          </Col>
          <Col xs={6}>
            <label>
              <Field
                name="channel"
                component="input"
                type="radio"
                value="phone"
                validate={Validator.required}
              />
              {t('phone')}
            </label>
          </Col>
        </FormGroup>
      </Col>}

      {codeSend && <Col style={{background: 'yellow'}}>
        <FormGroup row className="indented-form-group">
          <Field
            labelClassname="required"
            label={t('Code')}
            name="code"
            component="input"
            type="text"
            validate={[Validator.required]}
          />
        </FormGroup>
      </Col>}

      <Col style={{background: 'red'}}>
        <FormGroup row className="indented-form-group">
          {!editPhoneEnabled && <div>
            <span>PHONE PLACEHOLDER</span><br />
            <span onClick={handleEditPhone}>Edit phone number</span>
          </div>}

          {editPhoneEnabled && <Field
            name="phoneNumber"
            component={phoneFieldRenderer}
            validate={[Validator.required, Validator.phone]}
          />}
        </FormGroup>
      </Col>

      <Col>
        <FormGroup row className="indented-form-group">
          <Button submit disabled={props.submitting || props.invalid}>
            {editPhoneEnabled ? t('Change phone number') : codeSend ? t('Validate code') : t('Send code')}
          </Button>
        </FormGroup>
      </Col>
    </form>
  );
};

const mapStateToProps = state => ({
  formValues: getFormValues(formName)(state) || {}, //This basically gives us the form values in the props and it gets updated on keydown.
});

const decoratedComponent = connect(mapStateToProps, null)(PhoneVerifyForm)

export default (reduxForm({
  form: formName,
  enableReinitialize: true,
  shouldAsyncValidate: ({ trigger }) => ['blur'].includes(trigger),
})(decoratedComponent));
7kqas0il

7kqas0il1#

我也面临着同样的问题。

  • 在我以前的项目中,我使用了类组件,但我没有遇到这个问题。
  • 但是在功能组件中,要解决这个问题,您需要将phoneFieldRenderer函数放在组件之外(如@envy所述)。

相关问题