Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Keyboard Flickering on TextInput with secureTextEntry #39411

Closed
gcon97 opened this issue Sep 12, 2023 · 80 comments
Closed

Keyboard Flickering on TextInput with secureTextEntry #39411

gcon97 opened this issue Sep 12, 2023 · 80 comments
Labels
API: Keyboard Component: TextInput Related to the TextInput component. Issue: Author Provided Repro This issue can be reproduced in Snack or an attached project. Needs: Triage 🔍

Comments

@gcon97
Copy link

gcon97 commented Sep 12, 2023

Description

If you have 2 text inputs, (One with secure text entry enabled and the other set to disabled), When typing, highlighting and scrolling in the non-secure text entry, the keyboard will flicker.
This is an iOS issue only, I have tested this using iOS 17, on an iPhone 13 mini. I cannot repeat this issue in the simulator, only on the device.

It appears to be when iOS recognizes it as a login field, so it presents the auto-fill passwords UI. See the attached video on the flickering issue described.

RPReplay_Final1694522683.mov

React Native Version

0.72.4

Output of npx react-native info

System:
OS: macOS 13.4.1
CPU: (10) arm64 Apple M1 Pro
Memory: 115.16 MB / 16.00 GB
Shell:
version: "5.9"
path: /bin/zsh
Binaries:
Node:
version: 20.3.1
path: /opt/homebrew/bin/node
Yarn:
version: 1.22.19
path: /usr/local/bin/yarn
npm:
version: 9.6.7
path: /opt/homebrew/bin/npm
Watchman:
version: 2023.06.12.00
path: /opt/homebrew/bin/watchman
Managers:
CocoaPods:
version: 1.11.3
path: /usr/local/bin/pod
SDKs:
iOS SDK:
Platforms:
- DriverKit 22.4
- iOS 16.4
- macOS 13.3
- tvOS 16.4
- watchOS 9.4
Android SDK:
API Levels:
- "28"
- "31"
- "32"
- "33"
Build Tools:
- 30.0.2
- 30.0.3
- 32.0.0
- 33.0.0
- 34.0.0
System Images:
- android-30 | Google Play ARM 64 v8a
- android-33 | Google APIs ARM 64 v8a
- android-33 | Google Play ARM 64 v8a
- android-34 | Google APIs ARM 64 v8a
Android NDK: Not Found
IDEs:
Android Studio: 2022.1 AI-221.6008.13.2211.9619390
Xcode:
version: 14.3.1/14E300b
path: /usr/bin/xcodebuild
Languages:
Java:
version: 18.0.1.1
path: /usr/bin/javac
Ruby:
version: 2.6.10
path: /usr/bin/ruby
npmPackages:
"@react-native-community/cli": Not Found
react:
installed: 18.2.0
wanted: 18.2.0
react-native:
installed: 0.72.4
wanted: 0.72.4
react-native-macos: Not Found
npmGlobalPackages:
"react-native": Not Found
Android:
hermesEnabled: true
newArchEnabled: false
iOS:
hermesEnabled: true
newArchEnabled: false

Steps to reproduce

Have 2 TextInput components inside a view, one set with secureTextEntry, one without.

This issue is only seen on device, not in simulator

Snack, screenshot, or link to a repository

https://github.com/gcon97/KeyboardFlickeringDemo

@github-actions github-actions bot added API: Keyboard Component: TextInput Related to the TextInput component. labels Sep 12, 2023
@cortinico cortinico added the Issue: Author Provided Repro This issue can be reproduced in Snack or an attached project. label Sep 14, 2023
@tianlinjill
Copy link

I also encountered the similar issue when in login screen

@ShadReyes
Copy link

ShadReyes commented Sep 19, 2023

I am experiencing the same on login screens. It's a newer issue. It seems to be caused by the suggested autofill.

The problem is reduce by using default value prop passed to TextInput component that holds its own text ref and passes out ref value on change.

@ShadReyes
Copy link

ShadReyes commented Sep 19, 2023

I figured out the problem

It appears to be that at some point recently (pre iOS 17) a bug was introduced. Whenever secureTextEntry={false} and textContentType is set, various Text Input changes (typing, focus, etc...) will fire a native keyboardWillChangeFrame event that causes the keyboard to re-render. This also causes iOS's AutoFill QuickType Bar (forgive me if my terminology is incorrect) to flicker.

This can be especially problematic for any RN apps using KeyboardAvoidingView with iOS behavior={'position'} since it will cause a layout flicker as it adjusts to the disappearing and reappearing AutoFill QuickType Bar.

You can actually see the issue in native iOS apps:

  1. Go to the login screen of a native iOS app.
  2. Change focus from username and password fields.
  3. In many apps you can see a slight bounce as the keyboard animations handle the AutoFill QuickType Bar flicker.

For those who are using KeyboardAvoidingView (RN V0.72.* Patch Fix)

For those who are wrapping their text inputs in a <KeyboardAvoidingView behavior= 'position'}> and <ScrollView>, you are likely dealing with your screen jumping on text change and focus change.

This isn't a pretty solution (and keep in mind it does not fix the root issue of the keyboard re-render), but you can do the following **TEMPORARY and NOT fully tested** fix for this issue:

  1. Go to the file at: node_modules/react-native/Libraries/Components/Keyboard/KeyboardAvoidingView.js
  2. Add ignoreIOSKeyboardWillChangeEvents?: boolean | undefined; to the KeyboardAvoidingView props.
  3. Go to the types file at: node_modules/react-native/Libraries/Components/Keyboard/KeyboardAvoidingView.d.ts
  4. Add ignoreIOSKeyboardWillChangeEvents?: boolean | undefined; to the KeyboardAvoidingView props.
  5. Replace the const {duration, easing, endCoordinates} = this._keyboardEvent; line with the following:
const {duration, easing, endCoordinates} = this._keyboardEvent;

if(Platform.OS === 'ios' && duration === 0 && !!this.props.ignoreIOSKeyboardWillChangeEvents ) {
      return;
}
  1. Use patch package to save the changes.

be sure to set ignoreIOSKeyboardWillChangeEvents={true} with care. I, for example, am only using it on a login screen for a very specific keyboard avoiding use case scenario that I detail above. Hope this helps.

@ThorANilsson
Copy link

ThorANilsson commented Oct 3, 2023

RPReplay-Final1696326197.mov

I began seeing this after updating the device i test on (iPhone 14 Pro) to iOS 17. Using Expo Go. Very annoying...

What's interesting is that I am not experiencing this on another iPhone 11 Pro Max, also running iOS 17.

@ThorANilsson
Copy link

I believe this is caused by the "Passwords"-thing (see attached image) that appears on iOS when the OS believes you want to use a password from your keychain.

When I test on a phone that does not have a keychain, there is no jumping or flickering.
IMG-4401

@gcon97
Copy link
Author

gcon97 commented Oct 3, 2023

I can confirm that it is an issue with the Passwords option in the Keyboard toolbar. Seems to be an issue across iOS 17 rather than a ReactNative issue. (It also isn't fixed in iOS 17.1, so we may be waiting a while for a fix).

Closing as it isn't a React Native-specific issue.

@gcon97 gcon97 closed this as not planned Won't fix, can't repro, duplicate, stale Oct 3, 2023
@ThorANilsson
Copy link

ThorANilsson commented Oct 4, 2023

Adding textContentType='oneTimeCode' to your TextInput disables the Password toolbar, which also eliminates the described issue.

@Shubham0850
Copy link

@ThorANilsson I tried this, but it's not working for me.

@mkhoussid
Copy link

mkhoussid commented Oct 12, 2023

Here's what I did.

TL;DR: If it's a password field, on each change update the actual string value in a map, and then render the value as bullets ('•'). What we're essentially doing here is saying that all of our fields are just regular fields without autofill, but we can manipulate the value of the field, if it's a password field, if we pass a certain flag.

Somewhere created a file called maskMap.ts with the following:

export const maskMap = new Map<string, string>();

And in your custom TextField component (I'm assuming most of you have wrapped TextInput into one of your own TextField components):

import * as React from 'react';
import { TextInput } from 'react-native-paper';
import { maskMap } from './maskMap';

const PASSWORD_MASK_CHAR = '•';
. . .
// secureTextEntry determines whether or not this is a password field
const TextField = React.memo(({ onChange, secureTextEntry, ...props }: YourTextFieldProps) => {
  const [textFieldId] = React.useState(uuid()); // use whatever uuid generator you'd like
. . .
  React.useEffect(() => {
	  maskMap.set(textFieldId, '');

	  return () => {
		  maskMap.delete(textFieldId);
	  };
  }, [secureTextEntry]);

  const handleChange = React.useCallback((e: string) => {
	  if (secureTextEntry) {
		  const previousValue = maskMap.get(textFieldId) as string;
		  const formattedNewValue = e.replace(new RegExp(PASSWORD_MASK_CHAR, 'g'), '');

		  const newValue = previousValue + formattedNewValue;
		  onChange(newValue);
		  maskMap.set(textFieldId, previousValue + formattedNewValue);
	  } else {
		  onChange(e);
	  }
  }, [secureTextEntry]);

  const getValue = React.useCallback(() => {
	  if (!secureTextEntry) {
		  return value;
	  }

	  return value.replaceAll(/./g, PASSWORD_MASK_CHAR);
  }, [value, secureTextEntry, showText, maskMap]);
. . .

    return (
        . . .
            <TextInput
                value={getValue()}
                onChangeText={handleChange}
                textContentType='none' // add this
                . . .
            />
        . . .
    )
})

@Engazan
Copy link

Engazan commented Nov 17, 2023

how this can be closed if its still happening ?

it happends all the time when you have textContentType="password" or secureTextEntry

@ShadReyes
Copy link

@Engazan It's closed because it's an iOS bug. iOS started over-triggering keyboardWillChangeFrame events every time the input changes when the arguments you specified are implemented. We can't ignore this event because it's relied on for many component designs and reactivity. So, sadly we have to put in temporary patch fixes until Apple fixes it on their side.

@noahkurz
Copy link

noahkurz commented Nov 18, 2023

Adding textContentType='oneTimeCode' to your TextInput disables the Password toolbar, which also eliminates the described issue.

This works! Thank you!! Just saved my weekend lol

@chimiWangchukWangdi
Copy link

Any updates

@nguyenhuynhdeveloper
Copy link

I have found the solution. The error is caused by props value , you can hide the value and handle the logic with ref
Screenshot 2024-01-02 at 16 19 22
Uploading Screenshot 2024-01-02 at 16.19.22.png…

@nnphong1904
Copy link

Hi everyone, is there any update on this?

@xydian
Copy link

xydian commented Jan 25, 2024

Also happening on my side :) Seems to be an issue in flutter, too flutter/flutter#134723

@FemtDeveloper
Copy link

I have problem also in android,, can somebody helpme?

WhatsApp.Video.2024-02-06.at.03.17.54.mp4

@ugar0ff
Copy link

ugar0ff commented Feb 7, 2024

How to hide the "password" panel on the keyboard when we use secureTextEntry?

@RodrigueHunel
Copy link

Agree the issue should not be closed. These are all workarounds to a real issue, and doesn't seem like there are any other open issues in this repo that are directly related?

If there are, would be good to link here.

flutter/flutter#134723

@vitorbarros
Copy link

It should not be closed!

@irekrog
Copy link

irekrog commented Aug 30, 2024

It works even worse on iOS 18 (beta 8) 😕

@picardplaisimond
Copy link

picardplaisimond commented Sep 2, 2024

Are we the only persons in the world with this issue ? I don't understand why this flickering is not coming up on other apps? And why the simulator doesn't show the flickering ? iOS 17 is widely used right now. Can't ignore this.

@zhenkaGo
Copy link

zhenkaGo commented Sep 4, 2024

Try adding autoCorrect={false} to TextInput

@jsommer001
Copy link

Hate the .textContentType(.oneTimeCode) "fix".

Any update?

@Bialson
Copy link

Bialson commented Sep 11, 2024

I sometimes observe that problem in other apps so I guess there is something wrong with iOS. Hope iOS 18 will resolve the problems.

@irekrog
Copy link

irekrog commented Sep 11, 2024

I sometimes observe that problem in other apps so I guess there is something wrong with iOS. Hope iOS 18 will resolve the problems.

I'm not sure #39411 (comment)

@artiemez
Copy link

artiemez commented Oct 1, 2024

Try adding autoCorrect={false} to TextInput

Thanks! Helped in my case - I have email textInput with autoComplete set to username. Flickering is gone 👍

@verrannt
Copy link

verrannt commented Oct 1, 2024

Thanks! Helped in my case - I have email textInput with autoComplete set to username. Flickering is gone 👍

@artiemez Would you mind pasting your TextInput code? I still have the flickering, no matter what I try for autoComplete or autoCorrect.

(Testing on iPhone 13 Pro with iOS 18)

@artiemez
Copy link

artiemez commented Oct 1, 2024

Thanks! Helped in my case - I have email textInput with autoComplete set to username. Flickering is gone 👍

@artiemez Would you mind pasting your TextInput code? I still have the flickering, no matter what I try for autoComplete or autoCorrect.

(Testing on iPhone 13 Pro with iOS 18)

                <Input
                    size="lg"
                    className="text-center"
                    label="email address"
                    enterKeyHint="next"
                    onSubmitEditing={handleSubmit}
                    placeholder="email address"
                    autoCapitalize="none"
                    autoComplete="username"
                    keyboardType="email-address"
                    autoCorrect={false}
                    showClearButton
                    {...field}
                />

{...field} is react hook form controller props

@angelprzz
Copy link

I have the same problem with keyboardType="phone-pad" and autoComplete="tel"

@verrannt
Copy link

verrannt commented Oct 7, 2024

I was able to fix it by using what @artiemez proposed, but it's important to note that this only worked when using react-hook-form.

I.e. using autoComplete and autoCorrect on the normal React Native TextInput did nothing, but when wrapping it in a react-hook-form Controller and specifying keyboardType="email-address", then the jittering is gone for me, too.

@AbhijithKA2001
Copy link

I sometimes observe that problem in other apps so I guess there is something wrong with iOS. Hope iOS 18 will resolve the problems.

Could you please specify which apps you encountered the same issue in?

@paulohenriqueavguidance

Same issue here

@marcusflat
Copy link

In my case add keyboardType="email-address" solved this annoying bug

@nikoparas1
Copy link

nikoparas1 commented Nov 7, 2024

Has anyone discovered a good solution to this issue. In my Login/SignUp screens here are my Input Fields:
<View> <Text style={styles.label}>Email</Text> <TextInput value={email} onChangeText={setEmail} placeholder="[email protected]" style={styles.input} secureTextEntry={false} keyboardType="email-address" autoCorrect={false} /> </View>
`
Password
<TextInput
value={password}
onChangeText={setPassword}
placeholder="••••••••"
style={styles.input}
secureTextEntry

          />

`

Keep in mind that the keyboard only flickers when the email text input is changed, not the password.

@badddams
Copy link

I found this guys post on stackoverflow and it solved it for me. Simply adding autoCorrect= {false} to the input itself removes the flashing.

https://stackoverflow.com/a/78681410/4146738

@mhed89
Copy link

mhed89 commented Dec 16, 2024

in iOS 18.2 this is resolved.

edit: in iOS 18.2 the flickering is gone, apple fixed it with not closing the bar above the keyboard @Engazan

@Engazan
Copy link

Engazan commented Dec 16, 2024

in iOS 18.2 this is resolved.

It will be never resolved, use expo dom component and html input inside it (it's Webview but working rlly good)

Yea it sound crazy but its only working solution cuz React team does not want to fix it :/

Also why never ? Cuz it's 1 year and still no progress, even flutter fixed it ... it's kinda sad

@stewones
Copy link

stewones commented Feb 7, 2025

in iOS 18.2 this is resolved.

It will be never resolved, use expo dom component and html input inside it (it's Webview but working rlly good)

Yea it sound crazy but its only working solution cuz React team does not want to fix it :/

Also why never ? Cuz it's 1 year and still no progress, even flutter fixed it ... it's kinda sad

@Engazan I'm curious to see how Flutter fixes it. Do you have any links? From my experience, even SwiftUI inputs have this keyboard issue which is really annoying.

@stewones
Copy link

stewones commented Feb 7, 2025

in iOS 18.2 this is resolved.

edit: in iOS 18.2 the flickering is gone, apple fixed it with not closing the bar above the keyboard @Engazan

I'm running 18.3 and can confirm that the issue still exists.

@stewones
Copy link

stewones commented Feb 7, 2025

Adding textContentType='oneTimeCode' to your TextInput disables the Password toolbar, which also eliminates the described issue.

But then you lose the ability to autofill the password.
It seems like we have to rely on Apple's goodwill to resolve this.

@Psi-Quest
Copy link

Psi-Quest commented Feb 26, 2025

Not sure if the fix will be this simple for everyone, but in my case just removing the value={email} and defaultValue={email} props fixed everything and allowed me to keep textContentType={'emailAddress'} and the 'Passwords' autofill button iOS provides. Tested on 18.2 simulator and 18.3.1 physical device, Expo 51, react-native 0.74.5. Some of you may need the value prop for your use case, but if you don't, consider trying without.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
API: Keyboard Component: TextInput Related to the TextInput component. Issue: Author Provided Repro This issue can be reproduced in Snack or an attached project. Needs: Triage 🔍
Projects
None yet
Development

No branches or pull requests