Search code examples
react-nativenative-base

React Native Conditional style onFocus onBlur using Reusable Function Component


I have a reusable text input component using Native Base that I used on many screen, the goal is when text input on focus, the border changes color to #6852E1. When on blur, it changes to #8B8B8B.

The code below doesn't work like I want, or maybe there is something wrong with my code. How can I achieve that? Thanks

Here's the code

import React, { useState } from "react";
import { Dimensions } from "react-native";
import { Item, Input, Label, Icon } from "native-base";
import * as Font from "expo-font";

let borderColor;

// prettier-ignore
Font.loadAsync({
  Calibre_Regular: require("../assets/fonts/Calibre-Regular.ttf"),
  "Calibre_Regular": require("../assets/fonts/Calibre-Regular.ttf"),
});

const CustomTextInput = ({
  value,
  onChangeText,
  label,
  onSubmitEditing,
  getRef,
  onPress,
  onPress2,
  returnKeyType,
  keyboardType,
  editable,
  secureTextEntry,
  iconName,
  iconName2,
  whichStyle,
  defaultValue,
}) => {
  const { itemStyle1, itemStyle2, textInput, floatingLabel } = InputFieldStyles;
  return (
    <Item
      floatingLabel
      style={whichStyle ? itemStyle2 : itemStyle1}
      onPress={onPress2}
    >
      <Icon style={{ marginLeft: 10, color: "#8B8B8B" }} name={iconName2} />
      <Label style={floatingLabel}>{label}</Label>
      <Input
        onBlur={() => (borderColor = "#8B8B8B")}
        onFocus={() => (borderColor = "#6852E1")}
        style={textInput}
        blurOnSubmit={false}
        getRef={getRef}
        value={value}
        defaultValue={defaultValue}
        editable={editable}
        onChangeText={onChangeText}
        onSubmitEditing={onSubmitEditing}
        returnKeyType={returnKeyType}
        keyboardType={keyboardType}
        secureTextEntry={secureTextEntry}
      />
      <Icon name={iconName} onPress={onPress} />
    </Item>
  );
};

const InputFieldStyles = {
  textInput: {
    padding: 10,
    marginVertical: 10,
    fontSize: 16,
    color: "rgba(0, 0, 0, 0.87)",
    fontFamily: "Calibre_Regular",
  },
  floatingLabel: {
    marginLeft: 10,
    marginTop: 8,
    fontFamily: "Calibre_Regular",
  },
  itemStyle1: {
    marginLeft: 0,
    backgroundColor: "#FFF",
    borderColor: borderColor,
    // borderColor: "#6852E1",
    // borderColor: "#8B8B8B",
    borderBottomWidth: 3,
  },
  itemStyle2: {
    marginLeft: 0,
    backgroundColor: "#F6F7FC",
    borderColor: borderColor,
    borderBottomWidth: 3,
  },
  itemStyle3: {
    marginLeft: 0,
    backgroundColor: "#FFF",
    borderColor: "#6852E1",
    borderBottomWidth: 3,
  },
};

export { CustomTextInput };

this is my code with the right answer for those who needs

import React, { useState } from "react";
import { Dimensions } from "react-native";
import { Item, Input, Label, Icon } from "native-base";
import * as Font from "expo-font";

// prettier-ignore
Font.loadAsync({
  Calibre_Regular: require("../assets/fonts/Calibre-Regular.ttf"),
  "Calibre_Regular": require("../assets/fonts/Calibre-Regular.ttf"),
});

const CustomTextInput = ({
  value,
  onChangeText,
  label,
  onSubmitEditing,
  getRef,
  onPress,
  onPress2,
  returnKeyType,
  keyboardType,
  editable,
  secureTextEntry,
  iconName,
  iconName2,
  whichStyle,
  defaultValue,
}) => {
  const { itemStyle1, itemStyle2, textInput, floatingLabel } = InputFieldStyles;
  const [isFocused, setIsFocused] = useState(false);

  return (
    <Item
      floatingLabel
      style={whichStyle ? itemStyle2 : itemStyle1({ isFocused })}
      onPress={onPress2}
    >
      <Icon style={{ marginLeft: 10, color: "#8B8B8B" }} name={iconName2} />
      <Label style={floatingLabel}>{label}</Label>
      <Input
        onBlur={() => setIsFocused(false)}
        onFocus={() => setIsFocused(true)}
        style={textInput}
        blurOnSubmit={false}
        getRef={getRef}
        value={value}
        defaultValue={defaultValue}
        editable={editable}
        onChangeText={onChangeText}
        onSubmitEditing={onSubmitEditing}
        returnKeyType={returnKeyType}
        keyboardType={keyboardType}
        secureTextEntry={secureTextEntry}
      />
      <Icon name={iconName} onPress={onPress} />
    </Item>
  );
};

const InputFieldStyles = {
  textInput: {
    padding: 10,
    marginVertical: 10,
    fontSize: 16,
    color: "rgba(0, 0, 0, 0.87)",
    fontFamily: "Calibre_Regular",
  },
  floatingLabel: {
    marginLeft: 10,
    marginTop: 8,
    fontFamily: "Calibre_Regular",
  },
  itemStyle1: ({ isFocused }) => ({
    marginLeft: 0,
    backgroundColor: "#FFF",
    borderColor: isFocused ? "#6852E1" : "#8B8B8B",
    borderBottomWidth: 3,
  }),
  itemStyle2: {
    marginLeft: 0,
    backgroundColor: "#F6F7FC",
    borderBottomWidth: 3,
  },
  itemStyle3: {
    marginLeft: 0,
    backgroundColor: "#FFF",
    borderColor: "#6852E1",
    borderBottomWidth: 3,
  },
};

export { CustomTextInput };

Solution

  • Try this:

    const CustomTextInput = () => {
      const [isFocused, setIsFocused] = setState(false);
    
      return (
        /** ... */
        <Item style={itemStyle({ isFocused })}>
          >
          <Input
            onFocus={() => setIsFocused(true)}
            onBlur={() => setIsFocused(false)}
          />
        </Item>
        /** ... */
      );
    };
    
    itemStyle: ({ isFocused }) => ({
        borderColor: isFocused ? 'focused-color' : 'unfocused-color'
      }),