AstrOOnauta / react-native-international-phone-number

⚛️ International mobile phone number input component for React Native 📱
https://snack.expo.dev/@astroonauta/react-native-international-phone-number
ISC License
279 stars 52 forks source link

Resetting to default value #17

Closed martenjurgens closed 1 year ago

martenjurgens commented 1 year ago

Hey,

I couldn't figure it out myself, but is there a way to reset the field's value to it's default value?

I tried setting the defaultValue in React Hook Form and then using it's reset() fn, but all it does is that it overwrites the field's value as u can see on the picture.

image

AstrOOnauta commented 1 year ago

Hi @martenjurgens

Can you share your code, please?

🚀 AstrOOnauta 🚀

martenjurgens commented 1 year ago

If you comment in the defaultValues in the useForm hook, you can see the behaviour i described. With the solution you provided, it only resets to an empty field for me, and in the expo sandbox it doesn't even work.

https://snack.expo.dev/5BcxWgPqR

import { Text, SafeAreaView, StyleSheet } from 'react-native';
import PhoneInput from 'react-native-international-phone-number';
import {Controller, FieldValues, useForm} from 'react-hook-form';
import React, { useState } from "react";
import { TouchableOpacity, View } from "react-native";

export default function App() {
  const [selectedCountry, setSelectedCountry] = useState(undefined);
  const {control, handleSubmit, reset} = useForm({
    // defaultValues: {
    //   phoneNumber: "+3725622222"
    // }
  });

  return (
    <SafeAreaView style={styles.container}>
    <View style={{padding: 40, backgroundColor: "white"}}> 
      <Controller
          name="phoneNumber"
          control={control}
          render={({field: {onChange, value}}) => (
            <PhoneInput
              value={value}
              onChangePhoneNumber={onChange}
              selectedCountry={selectedCountry}
              onChangeSelectedCountry={setSelectedCountry}
              // defaultValue="+5584994689706"
              defaultValue="+1204345545"
            />
          )}
        />
        <TouchableOpacity
          style={{
            width: '100%',
            paddingVertical: 12,
            backgroundColor: '#2196F3',
            borderRadius: 4,
            marginTop: 10,
          }}
          onPress={() => reset()}>
          <Text
            style={{
              color: '#F3F3F3',
              textAlign: 'center',
              fontSize: 16,
              fontWeight: 'bold',
            }}>
            Reset
          </Text>
       </TouchableOpacity>
       </View>
    </SafeAreaView>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    backgroundColor: '#ecf0f1',
    padding: 8,
  },

});
AstrOOnauta commented 1 year ago

Hey @martenjurgens

Sorry, I didn't understand your issue before.

Please try again using the code below:

import {Text, SafeAreaView, StyleSheet} from 'react-native';
import PhoneInput from 'react-native-international-phone-number';
import {Controller, FieldValues, useForm} from 'react-hook-form';
import React, {useState} from 'react';
import {TouchableOpacity, View} from 'react-native';

export default function App() {
  const [selectedCountry, setSelectedCountry] = useState(undefined);
  const {control, handleSubmit, reset, setValue} = useForm({
    // defaultValues: {
    //   phoneNumber: "+3725622222"
    // }
  });

  function onSubmit(form) {
    reset();
    setValue('phoneNumber', form.phoneNumber);    <--- TRY THIS
  }

  return (
    <SafeAreaView style={styles.container}>
      <View style={{padding: 40, backgroundColor: 'white'}}>
        <Controller
          name="phoneNumber"
          control={control}
          render={({field: {onChange, value}}) => (
            <PhoneInput
              value={value}
              onChangePhoneNumber={onChange}
              selectedCountry={selectedCountry}
              onChangeSelectedCountry={setSelectedCountry}
              // defaultValue="+5584994689706"
              defaultValue="+1204345545"
            />
          )}
        />
        <TouchableOpacity
          style={{
            width: '100%',
            paddingVertical: 12,
            backgroundColor: '#2196F3',
            borderRadius: 4,
            marginTop: 10,
          }}
          onPress={handleSubmit(onSubmit)}>
          <Text
            style={{
              color: '#F3F3F3',
              textAlign: 'center',
              fontSize: 16,
              fontWeight: 'bold',
            }}>
            Reset
          </Text>
        </TouchableOpacity>
      </View>
    </SafeAreaView>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    backgroundColor: '#ecf0f1',
    padding: 8,
  },
});

This worked to reset the field's value to it's default value here in my tests .

🚀 AstrOOnauta 🚀

martenjurgens commented 1 year ago

Hey,

The solution you provided doesn't work. If u change the input's value to e.g "123123" and hit submit, then the form.phoneNumber is "123123" in the setValue('phoneNumber', form.phoneNumber), and not "+1204345545".

In case you didn't understand what I meant, I need a way to reset the PhoneInput's value back to default value after user presses something like a cancel changes button. The React Hook Form's reset() function works if the phoneNumber's default value is set inside the React Hook Form, but it breaks this library's functionality. As you can see on the picture, after resetting to default states, the phone number has the area code and the country isn't detected from the phone number.

image

AstrOOnauta commented 1 year ago

@martenjurgens thanks for your explanation, made it easier to analyze its logic...

Ok, you can do something like the code below:

import {Text, SafeAreaView, StyleSheet} from 'react-native';
import PhoneInput, {
  getCountryByPhoneNumber,
} from 'react-native-international-phone-number';
import {Controller, FieldValues, useForm} from 'react-hook-form';
import React, {useState} from 'react';
import {TouchableOpacity, View} from 'react-native';

export default function App() {
  const [selectedCountry, setSelectedCountry] = useState(undefined);
  const {control, handleSubmit, reset} = useForm({
    // defaultValues: {
    //   phoneNumber: "+3725622222"
    // }
  });

  const defaultPhoneInputValues = {
    defaultValue: '+1204345545',
    defaultCountry: getCountryByPhoneNumber('+1204345545'),
  };

  function onSubmit(form) {
    setSelectedCountry(undefined);
    reset();
    setSelectedCountry(defaultPhoneInputValues.defaultCountry); // <-- THIS LINE SET THE DEFAULT COUNTRY
                                                                //     AND, CONSEQUENTLY, SET AGAIN THE
                                                                //     DEFAULTCOUNTRY
  }

  return (
    <SafeAreaView style={styles.container}>
      <View style={{padding: 40, backgroundColor: 'white'}}>
        <Controller
          name="phoneNumber"
          control={control}
          render={({field: {onChange, value}}) => (
            <PhoneInput
              value={value}
              onChangePhoneNumber={onChange}
              selectedCountry={selectedCountry}
              onChangeSelectedCountry={setSelectedCountry}
              // defaultValue="+5584994689706"
              defaultValue="+1204345545"
            />
          )}
        />
        <TouchableOpacity
          style={{
            width: '100%',
            paddingVertical: 12,
            backgroundColor: '#2196F3',
            borderRadius: 4,
            marginTop: 10,
          }}
          onPress={handleSubmit(onSubmit)}>
          <Text
            style={{
              color: '#F3F3F3',
              textAlign: 'center',
              fontSize: 16,
              fontWeight: 'bold',
            }}>
            Reset
          </Text>
        </TouchableOpacity>
      </View>
    </SafeAreaView>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    backgroundColor: '#ecf0f1',
    padding: 8,
  },
});

Please try again and let me know if it worked

🚀 AstrOOnauta 🚀

martenjurgens commented 1 year ago

@AstrOOnauta Thank you very much! Unbelievable I didn't think of it myself, sorry about that.