react-phone-number-input icon indicating copy to clipboard operation
react-phone-number-input copied to clipboard

(React Native) Can this package be used in the React Native?

Open irsyaadbp opened this issue 6 years ago • 70 comments

Can this package be used in the react native

irsyaadbp avatar Nov 12 '19 20:11 irsyaadbp

Update: Yes, "without country select" component.

First, create PhoneTextInput.js file:

import React, { useCallback } from 'react'
import PropTypes from 'prop-types'
import { TextInput } from 'react-native'

function PhoneTextInput({ 
  placeholder, 
  autoComplete, 
  autoFocus, 
  value, 
  onChange 
}, ref) {
  // Instead of `onChangeText` it could use `onChange` and get `value` from `nativeEvent.text`.
  const onChangeText = useCallback((value) => {
    onChange({
      preventDefault() { this.defaultPrevented = true },
      target: { value }
    })
  }, [onChange])
  return (
    <TextInput
      ref={ref}
      placeholder={placeholder}
      autoFocus={autoFocus}
      autoCompleteType={autoComplete}
      keyboardType="phone-pad"
      onChangeText={onChangeText}
      value={value}/>
  )
}

PhoneTextInput = React.forwardRef(PhoneTextInput)

PhoneTextInput.propTypes = {
  placeholder: PropTypes.string,
  autoComplete: PropTypes.string,
  autoFocus: PropTypes.bool,
  value: PropTypes.string,
  onChange: PropTypes.func.isRequired
}

export default PhoneTextInput

Then, in a React Native application:

import React, { useState } from 'react'
import PhoneInput from 'react-phone-number-input/input'
import PhoneTextInput from './PhoneTextInput'

function Example() {
  const [value, setValue] = useState()
  return (
    <PhoneInput
      style={...}
      smartCaret={false}
      inputComponent={PhoneTextInput}
      defaultCountry="US"
      value={value}
      onChange={setValue} /> 
  )
}

Report in this issue if it works.

catamphetamine avatar Nov 12 '19 20:11 catamphetamine

Also see the previous question: https://github.com/catamphetamine/react-phone-number-input/issues/283#issuecomment-552244455

catamphetamine avatar Nov 12 '19 20:11 catamphetamine

@catamphetamine "without country select" doesn't work with react native. Although I am trying out a simple example with text input and the libphonenumber-js to work out something. Till now what I have done has worked till some extent but it will be great if you could help me in understanding how the smart caret works in your react component. For now the caret has a jumping effect when it meets with a blank space or a bracket.

whimsicaldreamer avatar Jan 20 '20 20:01 whimsicaldreamer

@whimsicaldreamer

"without country select" doesn't work with react native.

How are you using it? Is it v3?

Till now what I have done has worked till some extent but it will be great if you could help me in understanding how the smart caret works in your react component. For now the caret has a jumping effect when it meets with a blank space or a bracket.

Smart caret is using input-format library.

catamphetamine avatar Jan 20 '20 20:01 catamphetamine

@catamphetamine

How are you using it?

I am using it as per the instructions in the readme for using "without country select"

Is it v3?

Yes, the latest. 3.0.13.

Smart caret is using input-format library.

Any suggestions on how to use with react native input or how you implement it with react input?

whimsicaldreamer avatar Jan 21 '20 03:01 whimsicaldreamer

I am using it as per the instructions in the readme for using "without country select"

Then it won't work because React Native most likely doesn't support <select/>. https://github.com/catamphetamine/react-phone-number-input/blob/master/source/PhoneInput.js See if inputComponent={Select} fixes the issue.

Any suggestions on how to use with react native input or how you implement it with react input?

See the InputSmart.js file of this library if you want to copy the behavior.

catamphetamine avatar Jan 21 '20 11:01 catamphetamine

Then it won't work because React Native most likely doesn't support <select/>

Yes you are correct.

See if inputComponent={Select} fixes the issue

You mean to pass in the react native TextInput component here?

whimsicaldreamer avatar Jan 21 '20 17:01 whimsicaldreamer

You mean to pass in the react native TextInput component here?

Yes.

catamphetamine avatar Jan 21 '20 17:01 catamphetamine

Maybe something like:

import React from 'react'
import { TextInput } from 'react-native'

export default function PhoneTextInput({ 
  placeholder, 
  autoComplete, 
  autoFocus, 
  value, 
  onChange 
}) {
  return (
    <TextInput
      placeholder={placeholder}
      autoFocus={autoFocus}
      autoCompleteType={autoComplete}
      keyboardType="phone-pad"
      onChangeText={onChange}
      value={value}
    />
  );
}

Report if it works.

catamphetamine avatar Jan 21 '20 17:01 catamphetamine

Ok, copying the above as a separate component and calling it as following:

<PhoneInput
      country="IN"
      inputComponent={ PhoneTextInput } // <= From your example component above
      value={this.state.mobile_number}
      onChange={ this._phoneInputHandler }
/>

Let me know if my interpretation is correct.

whimsicaldreamer avatar Jan 21 '20 18:01 whimsicaldreamer

Yes, see if it works. I don't have React Native so I didn't check.

catamphetamine avatar Jan 21 '20 18:01 catamphetamine

@catamphetamine On Load I get a warning: Function components cannot be given refs. Attempts to access this ref will fail. Did you mean to use React.forwardRef()?

On typing in the first digit, I also get an error: TypeError: Undefined is not an object(evaluating 'input.value')

whimsicaldreamer avatar Jan 22 '20 05:01 whimsicaldreamer

On Load I get a warning: Function components cannot be given refs. Attempts to access this ref will fail. Did you mean to use React.forwardRef().

The component uses React.forwardRef(). I added ref={...} on demo page to "without country select" and it didn't print any warning.

On typing in the first digit, I also get an error:

input.value is being accessed from input-format package. input is the ref. ref isn't working in your case for some reason, so input is undefined in input-format package.

Actually, we didn't forward ref in <PhoneTextInput/>.

See if this works:

import React from 'react'
import PropTypes from 'prop-types'
import { TextInput } from 'react-native'

function PhoneTextInput({ 
  placeholder, 
  autoComplete, 
  autoFocus, 
  value, 
  onChange 
}, ref) {
  return (
    <TextInput
      ref={ref}
      placeholder={placeholder}
      autoFocus={autoFocus}
      autoCompleteType={autoComplete}
      keyboardType="phone-pad"
      onChangeText={onChange}
      value={value}
    />
  )
}

PhoneTextInput = React.forwardRef(PhoneTextInput)

PhoneTextInput.propTypes = {
  placeholder: PropTypes.string,
  autoComplete: PropTypes.string,
  autoFocus: PropTypes.bool,
  value: PropTypes.string,
  onChange: PropTypes.func.isRequired
}

export default PhoneTextInput

catamphetamine avatar Jan 22 '20 21:01 catamphetamine

input.value is being accessed from input-format package.

Do I need to install the input-format package separately?? Since I still get the error: TypeError: Undefined is not an object(evaluating 'input.value'). Although the warning is gone.

whimsicaldreamer avatar Jan 23 '20 10:01 whimsicaldreamer

Do I need to install the input-format package separately?

No, it's installed automatically. The code above should work because it forwards ref now. Did the forwardRef warning disappear?

catamphetamine avatar Jan 23 '20 15:01 catamphetamine

Yes, the forward ref warning disappeared but I get the TypeError.

whimsicaldreamer avatar Jan 23 '20 15:01 whimsicaldreamer

Doesn’t it show a stack trace?

On Thu, 23 Jan 2020 at 18:23, Ayan Dey [email protected] wrote:

Yes, the forward ref warning disappeared but I get the TypeError.

— You are receiving this because you were mentioned.

Reply to this email directly, view it on GitHub https://github.com/catamphetamine/react-phone-number-input/issues/296?email_source=notifications&email_token=AADUP3ZZJFBH2G4LJ3EFHGTQ7GZAXA5CNFSM4JMIZADKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEJXXIII#issuecomment-577729569, or unsubscribe https://github.com/notifications/unsubscribe-auth/AADUP33YW75QSG3MMW455OLQ7GZAXANCNFSM4JMIZADA .

catamphetamine avatar Jan 23 '20 15:01 catamphetamine

I guess input-format is only for react.

Screenshot_2020-01-23-22-09-05-727_com furry

whimsicaldreamer avatar Jan 23 '20 15:01 whimsicaldreamer

So, the error originates at that function: https://github.com/catamphetamine/input-format/blob/26abb77bec3ac5984f7fe99408846464fda6136a/source/input%20control.js#L35-L38 Called from here: https://github.com/catamphetamine/input-format/blob/26abb77bec3ac5984f7fe99408846464fda6136a/source/react/Input.js#L35-L41 And input there is ref.current. There, for some reason ref.current is undefined.

I read a bit about React Native, and found out that even if the input wasn't undefined, still there's no input.value property, so I guess input-format won't work in React Native. The alternative then is passing smartCaret={false} property when creating a <PhoneInput/> "without country select" component element. https://github.com/catamphetamine/react-phone-number-input/blob/d84e5ad751c60b083850a634899d9ad5e5039ce9/source/PhoneInput.js#L103

So, see if such code works:

import PhoneInput from 'react-phone-number-input/input`

<PhoneInput smartCaret={false} .../>

catamphetamine avatar Jan 24 '20 00:01 catamphetamine

On adding smartCaret: { false } I receive a TypeError on keying in numbers. This is what I have currently:

<PhoneInput
       style={ styles.phoneNumberInput }
       smartCaret={ false }
       country="IN"
       inputComponent={ PhoneTextInput }
       value={ this.state.mobile_number }
       onChange={ (number) => this._phoneInputHandler(number) }
/> 

Screenshot_2020-01-24-11-38-40-638_com furry

whimsicaldreamer avatar Jan 24 '20 06:01 whimsicaldreamer

Oh, yes, change onChangeText to onChange in <PhoneTextInput/>.

On Fri, 24 Jan 2020 at 09:10, Ayan Dey [email protected] wrote:

On adding smartCaret: { false } I receive a TypeError.

[image: Screenshot_2020-01-24-11-38-40-638_com furry] https://user-images.githubusercontent.com/8104493/73048198-4c0e9380-3e9e-11ea-974a-45ba4b51a49e.jpg

— You are receiving this because you were mentioned.

Reply to this email directly, view it on GitHub https://github.com/catamphetamine/react-phone-number-input/issues/296?email_source=notifications&email_token=AADUP35VM5E462NIODWTGOTQ7KA5RA5CNFSM4JMIZADKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEJZ2OUY#issuecomment-578004819, or unsubscribe https://github.com/notifications/unsubscribe-auth/AADUP3ZMANUMVUAR77VMTKDQ7KA5RANCNFSM4JMIZADA .

catamphetamine avatar Jan 24 '20 09:01 catamphetamine

Screenshot_2020-01-24-16-31-41-572_com furry

whimsicaldreamer avatar Jan 24 '20 11:01 whimsicaldreamer

So event.target.value is undefined at this line of code: https://github.com/catamphetamine/react-phone-number-input/blob/d84e5ad751c60b083850a634899d9ad5e5039ce9/source/InputBasic.js#L26 You can add some kind of console.log(event.target.value) in onChange to see what's the value there.

<PhoneTextInput onChange={event => { console.log(event); onChange(event); }}/>

catamphetamine avatar Jan 24 '20 11:01 catamphetamine

The log turns out to be huge! So I am pasting the nativeEvent right after I typed a single digit 9:

"nativeEvent": {"eventCount": 1, "target": 43, "text": "9"}, "target": 43, "timeStamp": 1579864644085, "type": undefined}

whimsicaldreamer avatar Jan 24 '20 11:01 whimsicaldreamer

Huh, so target is a number in React Native? How does one get value then. Well, ok, then try this instead:

<PhoneTextInput onTextChange={value => onChange({
  preventDefault() { this.defaultPrevented = true },
  target: { value }
})}/>

It creates an event stub from a value.

Perhaps there're more correct ways.

catamphetamine avatar Jan 24 '20 11:01 catamphetamine

I guess we get the values from nativeEvent.text.

whimsicaldreamer avatar Jan 24 '20 11:01 whimsicaldreamer

<PhoneTextInput onTextChange={value => onChange({
  preventDefault() { this.defaultPrevented = true },
  target: { value }
})}/>

Where should I try the above?

whimsicaldreamer avatar Jan 24 '20 11:01 whimsicaldreamer

@whimsicaldreamer

I guess we get the values from nativeEvent.text.

Maybe. That could be a second route. Not yet though.

Where should I try the above?

I meant:

<TextInput onTextChange={(value) => onChange({
  preventDefault() { this.defaultPrevented = true },
  target: { value }
})}/>

catamphetamine avatar Jan 24 '20 12:01 catamphetamine

My current implementation was as following:

<PhoneInput
    style={ styles.phoneNumberInput }
    smartCaret={ false }
    country="IN"
    inputComponent={ PhoneTextInput }
    value={ this.state.mobile_number }
    onChange={ (number) => this._phoneInputHandler(number) }
/>

where PhoneTextInput is:

function PhoneTextInput({
        placeholder,
        autoComplete,
        autoFocus,
        value,
        onChange,
        style,
    }, ref) {
    return (
        <TextInput
            style={ style }
            ref={ ref }
            placeholder={ placeholder }
            autoFocus={ autoFocus }
            autoCompleteType={ autoComplete }
            keyboardType="phone-pad"
            onChange={ event => { console.log(event); onChange(event); } }
            value={ value }
            onTextChange={value => onChange({
                preventDefault() {
                    this.defaultPrevented = true
                },
                target: {value}
            })}
        />
    );
}

PhonePadInput = React.forwardRef(PhoneTextInput);

I am not sure if this is the way you mean.

On a side note, I have been trying out to implement this on my own without react-phone-number-input library and using only libphonenumber-js. I have been able to get the formatting done on the fly but one issue arises and that is on erasing a phone number entered. The issue is similar to this: https://github.com/catamphetamine/libphonenumber-js/issues/225. If you would like to know how I am doing it, I would love to paste it in here.

whimsicaldreamer avatar Jan 24 '20 12:01 whimsicaldreamer

Remove onChange={ event => { console.log(event); onChange(event); } } because it's now replaced with onChangeText.

If you would like to know how I am doing it, I would love to paste it in here.

I won't assist with any custom components, only with parts of react-phone-number-input.

catamphetamine avatar Jan 24 '20 12:01 catamphetamine