简体   繁体   English

React-Phone-Number-Input + React-Hook-Form:如何在控制器验证中获取当前国家代码?

[英]React-Phone-Number-Input + React-Hook-Form: How to get current country code in controller validation?

I'm using react-phone-number-input library.我正在使用react-phone-number-input库。 The phone number input is not required but if the number is present I wish it could be validated before the form is sent.不需要输入电话号码,但如果该号码存在,我希望在发送表单之前对其进行验证。

If the cellphone field is pristine / left untouched when form is submitted then isValid accepts undefined (valid state).如果提交表单时cellphone字段是原始的/未触及,则isValid接受undefined (有效状态)。

If country code is changed right away (without actually inputting the number) isValid accepts the selected country's calling code (eg +46 for Sweden).如果国家代码立即更改(没有实际输入号码), isValid接受所选国家的呼叫代码(例如瑞典的+46 )。 This is still a perfectly valid case.这仍然是一个完全有效的案例。

When accessed in the isValid function the phoneCountryCode always holds the previous selected value.isValid函数中访问时, phoneCountryCode始终保存先前选择的值。 So there's always a disparity between the validated phone number and the current country code.因此,经过验证的电话号码和当前的国家代码之间总是存在差异。 I'm not sure if the problem is library-specific, maybe it's my mistake.我不确定问题是否是特定于库的,也许是我的错误。 How do I get rid of the mentioned disparity?我如何摆脱提到的差异?

I made a reproduction on CodeSandbox .在 CodeSandbox 上进行了复制

import PhoneInput, {
  parsePhoneNumber,
  getCountryCallingCode
} from "react-phone-number-input";

const [phoneCountryCode, phoneCountryCodeSetter] = useState('DE');

<Controller 
  name="cellphone"
  rules={{
    validate: {
      isValid: value => {
        if(value) {
          const callingCode = getCountryCallingCode(phoneCountryCode); 
          if(! new RegExp(`^\\+${callingCode}$`).test(value)) {
            // The parsePhoneNumber utility returns null 
            // if provided with only the calling code
            return !!parsePhoneNumber(value);
          }
        }
        return true;
      }
    }
  }}
  control={control}
  render={({ field }) => (
    <PhoneInput 
      {...field}
      onCountryChange={(v) => phoneCountryCodeSetter(v)}
      limitMaxLength={true}
      international={true}
      defaultCountry="DE"
    />
  )}
/>

It's a react specific, nothing wrongs in the library.这是一个特定的反应,图书馆没有错。 React never update state immediately, state updates in react are asynchronous; React 从不立即更新状态,React 中的状态更新是异步的; when an update is requested there's no guarantee that the updates will be made immediately.当请求更新时,不能保证会立即进行更新。 Then updater functions enqueue changes to the component state, but react may delay the changes.然后更新函数将更改加入到组件状态,但反应可能会延迟更改。

for example:例如:

const [age, setAge] = useSate(21);
const handleClick = () => {
    setAge(24)
    console.log("Age:", age);
}

You'll see 21 logged in the console .您将在控制台中看到 21 登录

So this is how react works.这就是 react 的工作原理。 In your case, as you change country this "onCountryChange" event triggers updating function to update the state and to validate the phone number but the state is not updated yet that's why it is picking the previous countryCode value(Do console log here).在您的情况下,当您更改国家/地区时,此“onCountryChange”事件会触发更新功能以更新状态并验证电话号码,但状态尚未更新,这就是它选择以前的 countryCode 值的原因(在此处进行控制台日志)。

To understand this more clearly put this code inside your component.为了更清楚地理解这一点,请将此代码放入您的组件中。

useEffect(() => {
    console.log("useEffect: phoneCountryCode", phoneCountryCode);
  }, [phoneCountryCode]);


console.log(phoneCountryCode, value); // inside isValid()

useEffect callback will be called when phoneCountryCode value is updated and console.log inside isValid() will be called before the state gets updated.更新 phoneCountryCode 值时将调用 useEffect 回调,并且将在状态更新之前调用 isValid() 中的 console.log。

Hopes this makes sense.希望这是有道理的。 Happy Coding!!编码快乐!!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM