react-native: Android TextInput font family incorrect after switching `secureTextEntry`

This appears to be an old issue, but i’m seeing it now in 0.63.3 it’s not occurring in IOS

#6149, #5710

Description

When secureTextEntry={true} for TextInput, the font-family for placeholder is ignored:

React Native version:

System: OS: macOS 10.15.4 CPU: (16) x64 Intel® Core™ i9-9880H CPU @ 2.30GHz Memory: 596.29 MB / 32.00 GB Shell: 5.8 - /usr/local/bin/zsh Binaries: Node: 12.18.3 - /usr/local/bin/node Yarn: 1.17.3 - ~/.yarn/bin/yarn npm: 6.14.6 - /usr/local/bin/npm Watchman: 4.9.0 - /usr/local/bin/watchman Managers: CocoaPods: 1.9.1 - /Users/timo/.rvm/rubies/ruby-2.4.1/bin/pod SDKs: iOS SDK: Platforms: iOS 14.0, DriverKit 19.0, macOS 10.15, tvOS 14.0, watchOS 7.0 Android SDK: API Levels: 22, 23, 24, 25, 26, 27, 28, 29 Build Tools: 23.0.1, 23.0.2, 23.0.3, 25.0.0, 25.0.1, 25.0.2, 25.0.3, 26.0.1, 26.0.2, 27.0.0, 27.0.1, 27.0.2, 27.0.3, 28.0.0, 28.0.2, 28.0.3, 29.0.2 System Images: a…google_apis | Google APIs Intel x86 Atom Sys…, a…-23 | Intel x86 Atom, a… | Intel x86 Atom_64, a…google_apis | Google APIs Intel x86 Atom Sys…, a…gle_apis | Google APIs Intel x86 Atom_64 …, a…google_apis | Google APIs Intel x86 Atom Sys…, a…google_apis | Google APIs Intel x86 Atom Sys…, a…s_playstore | Google Play Intel x86 Atom Sys…, a…google_apis | Google APIs Intel x86 Atom Sys…, a…gle_apis | Google APIs Intel x86 Atom_64 …, a…s_playstore | Google Play Intel x86 Atom Sys… Android NDK: Not Found IDEs: Android Studio: Not Found Xcode: 12.0.1/12A7300 - /usr/bin/xcodebuild Languages: Python: 3.8.5 - /usr/local/bin/python npmPackages: @react-native-community/cli: Not Found react: 16.13.1 => 16.13.1 react-native: 0.63.3 => 0.63.3 npmGlobalPackages: react-native: Not Found

Steps To Reproduce

Provide a detailed list of steps that reproduce the issue.

<TextInput
  id={'email'}
  placeholder={'Email'}
  secureTextEntry={false}
  style={{fontFamily: 'Helvetica', fontSize: 14, fontWeight: '400' }}
/>

<TextInput
  id={'password'}
  placeholder={'Password'}
  secureTextEntry={true}
  style={{fontFamily: 'Helvetica', fontSize: 14, fontWeight: '400' }}
/>


Expected Results

i expect the style rules to be applied

Snack, code example, screenshot, or link to a repository:

Screen Shot 2020-10-07 at 11 13 42 AM

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Reactions: 52
  • Comments: 45 (4 by maintainers)

Commits related to this issue

Most upvoted comments

I fixed this setting font family by ref in TextInput using useEffect and useRef.

So, i think is better create your Input component with this code to get easier to use.

Screenshot from 2020-10-17 17-04-21

-> Edit You can also use a better solution created by @everthon-carniel https://github.com/facebook/react-native/issues/30123#issuecomment-815133549 (answered later in this post)

<TextInput 
   placeholder="some text" 
   ref={ref => ref && ref.props && ref.setNativeProps({ 
          text: ref.props.value, 
          style: { fontFamily: 'sans-serif' } 
   })}
/>

Any questions read https://github.com/facebook/react-native/issues/30123#issuecomment-847354613 or the other solutions ahead of this post.

The problem continues to happen in React Native 0.64. It’s not necessary to use useRef or useEffect to change the fontFamily. You can do this directly in the component reference. As below:

<TextInput ref={ref => ref && ref.setNativeProps({ style: { fontFamily: 'FONT_NAME' } })} />

I’m also facing this issue after upgrading from 0.62.2 to 0.63.3

Bug reproduced with v0.64.0…

I can confirm that bug is back in v0.64.0

I’m facing the same issue. I’d be ideal not to add extra code to something that should work natively 😕.

Here’s the doc to the above answer: https://reactnative.dev/docs/direct-manipulation/

If for some reason you are obfuscating and then showing the password from an action, you could do something like this

 useEffect(() => {
    const { fontFamily, secureTextEntry } = props;

    if (textInputRef.current && fontFamily) {
      textInputRef.current.setNativeProps({
         secureTextEntry,
        style: {
          fontFamily,
        },
      });
    }
  }, [secureTextEntry]);

Works fine for me with 0.63.4 version

Had same issue too (RN 0.63.3, running on Android), In a class based component, and fortunately, I fixed it by applying the font of the ref in componentDidMount using setNativeProps as @helder9991 mentioned. (note: in my case am creating a component based on TextInput)

export default class CustomTextInput extends Component {

    inputRef: any;

    componentDidMount() {
        // here
        this.inputRef.setNativeProps({
            style: {
                fontFamily: 'YOUR_FONT_GOES_HERE',
            },
        });
    }

    render() {

        return (
            <TextInput
                ref={(ref) => (this.inputRef = ref)}  // here
                selectionColor={color}
                placeholderTextColor={color}
                value={value}
                placeholder={placeHolder}
                onChangeText={(text) => this.onTxtChange(text)}
                autoCapitalize={'none'}
                autoCorrect={false}
                autoFocus={false}
                textAlignVertical={'center'}
                {...props}
            />
        );
    }

This is Issue isn’t closed and not resolved in 0.64.2 so please re-open it!

I fixed this setting font family by ref in TextInput using useEffect and useRef.

So, i think is better create your Input component with this code to get easier to use.

Screenshot from 2020-10-17 17-04-21

setNativeprops isn’t function

Bug reproduced with v0.64.1

$ npm list react-native
App@2.0.0 C:\Projects\mercado-app
`-- react-native@0.64.1

@melero2000 check if you provide a value property to your input and onChangeText one as well

@DracotMolver Thanks, just what I needed! I had a password field that rendered conditionally and used this:

function Example () {
  const passwordInput = useRef<TextInput>(null)
  useEffect(() => {
    passwordInput.current?.setNativeProps({ style: theme.input })
  }, [condition])
  return condition ? ... : <TextInput style={theme.input} secureTextEntry ref={passwordInput} />
}

Hi guys,

I’m getting the same result as @melero2000 with RN 0.64.1. Any idea how to fix this?

The function ‘setNativeProps’ is overwriting the property ‘text’ to a empty string. You can see this setting: setNativeProps( { text: "some text" } )

You can fix this problem setting the current value of input in the ‘setNativeProps’ function (remember to check if ref.props exists)

 <TextInput 
      placeholder="some text" 
      ref={ref => ref && ref.props && ref.setNativeProps({ 
             text: ref.props.value, 
             style: { fontFamily: 'sans-serif' } 
      })}
    />

You can also fix this problem using ‘useState’ from react library.

import React, { useState } from 'react';
import { TextInput } from 'react-native';

export default function App() {
  const [inputValue, setInputValue] = useState('');
  return (
    <TextInput 
      placeholder="some text" 
      value={inputValue} // show the value of "inputValue" in TextInput
      onChangeText={(text) => setInputValue(text)} // if the text change, you call the function to save in "inputValue" variable
      ref={ref => ref && ref.setNativeProps({ style: { fontFamily: 'sans-serif' } })}
      />
  ); 
}

Adding the following to the TextInputField component I mentioned above fixes the issue:

    const [reapplyInputFontFamilyStyle, setReapplyInputFontFamilyStyle] = React.useState<TextStyle | null>(null);
    React.useEffect(() => {
        setReapplyInputFontFamilyStyle(styles.inputFontFamily);

        /*
         * Re-applying styles in setTimeout for updates to the secure text entry flag,
         * as otherwise the style might be wrong afterwards.
         * In order for this to work, it is necessary to temporary remove the style.
         * In most cases not necessary, as the flag will not change after component mount.
         */
        setTimeout(() => {
            setReapplyInputFontFamilyStyle(null);
            setReapplyInputFontFamilyStyle(styles.inputFontFamily);
        }, 0);
    }, [secureTextEntry]);