Focus style for TextInput in react-native

The best way to control the style when the element is focused / blurred is to create your own TextInput wrapper

export const MyAppTextInput = (props) => {
  return (
    <TextInput
      {...props}
    />
  );
};

Note that {...props} will pass in any property you already set or available for TextInput.

Then extend the above component by adding state to apply styles when focus / blur

export const MyAppTextInput = (props) => {
  const [isFocused, setIsFocused] = useState(false);
  return (
    <TextInput
      {...props}
      style={[props.style, isFocused && {borderWidth: 5, borderColor: 'blue'}]}
      onBlur={() => setIsFocused(false)}
      onFocus={() => setIsFocused(true)}
    />
  );
};

And remember when you use the component to bind the value like in the example (see value={passwordText}); otherwise the value will disappear on blur as a new render commences after the state change.

<MyAppTextInput
          style={styles.input}
          value={passwordText}
          textContentType="password"
          autoCompleteType="off"
          secureTextEntry
          onChangeText={text => {
            setPasswordText(text);
          }}
        />

You can of course avoid creating a wrapper but if you have more than one input it will create a mess in your input(s) parent components as you will have to add repeating logic.


Use refs, DirectManipulation and setNativeProps for more performance: https://facebook.github.io/react-native/docs/direct-manipulation.

class MyInput extends Component {
  focusedInput = () => { 
    this.textInput.setNativeProps({
      style: { backgroundColor: 'green' }
    }) 
  }

  blurredInput = () => { 
    this.textInput.setNativeProps({
      style: { backgroundColor: 'yellow' }
    }) 
  }

  render () {
      return <TextInput 
                ref={c => { this.textInput = c}} 
                style={styles.textInput}
                onFocus={this.focusedInput}
                onBlur={this.blurredInput} />
  }

}

const stylesObj = { textInput: { height: 50, fontSize: 15, backgroundColor: 'yellow', color: 'black', } }

const styles = StyleSheet.create(stylesObj)

This updates the TextInput component directly without re-rendering the component hierarchy.


You can achieve this by passing in the onFocus and onBlur events to set and unset styles when focused and blurred:

  onFocus() {
    this.setState({
        backgroundColor: 'green'
    })
  },

  onBlur() {
    this.setState({
      backgroundColor: '#ededed'
    })
  },

And then, in the TextInput do this:

<TextInput 
    onBlur={ () => this.onBlur() }
    onFocus={ () => this.onFocus() }
    style={{ height:60, backgroundColor: this.state.backgroundColor, color: this.state.color }}  />

I've set up a full working project here. I hope this helps!

https://rnplay.org/apps/hYrKmQ

'use strict';

var React = require('react-native');
var {
  AppRegistry,
  StyleSheet,
  Text,
  View,
  TextInput
} = React;

var SampleApp = React.createClass({

  getInitialState() {
    return {
        backgroundColor: '#ededed',
      color: 'white'
    }
  },

  onFocus() {
        this.setState({
        backgroundColor: 'green'
    })
  },

  onBlur() {
    this.setState({
      backgroundColor: '#ededed'
    })
  },

  render: function() {
    return (
      <View style={styles.container}>
       <TextInput 
        onBlur={ () => this.onBlur() }
        onFocus={ () => this.onFocus() }
        style={{ height:60, backgroundColor: this.state.backgroundColor, color: this.state.color }}  />
      </View>
    );
  }
});

var styles = StyleSheet.create({
  container: {
    flex: 1,
    marginTop:60
  }
});

AppRegistry.registerComponent('SampleApp', () => SampleApp);