Niko Konovalov
Niko Konovalov

Reputation: 191

How to use custom TextInput component in other module and handle data?

I'm facing an issue quite some time, I can seem to get how to extract data from my register page to my dynamic TextInput component Here is My Register Page Code:

import React, { Component } from "react";
import firebase from "../util/firebase";
import {
  StyleSheet,
  Text,
  View,
  TouchableOpacity,
  TextInput,
  ActivityIndicator,
  Alert,
} from "react-native";
import {
  widthPercentageToDP as wp,
  heightPercentageToDP as hp,
} from "react-native-responsive-screen";

import RegisterTextBox from "../components/registerInput";

export default class Register extends React.Component {
  //State Constructor
  constructor(props) {
    super(props);
    this.state = {
      confirmPassword: "",
      email: "",
      password: "",
      isLoading: false,
      buttonColor: "#8b898a",
    };
  }
  //Change Button Color
  changeColor() {
    let currentColor = this.state.buttonColor;
    if (
      this.state.email != "" &&
      this.state.password != "" &&
      this.state.confirmPassword != ""
    ) {
      currentColor = "#7356bf";
    } else currentColor = "#8b898a";
    this.setState({ buttonColor: currentColor });
  }
  //Update Input State to Current Input Value
  updateInputVal = (val, prop) => {
    const state = this.state;
    state[prop] = val;
    this.changeColor();
  };
  //Register Function
  registerUser = () => {
    //If Input Blank Return Alert
    if (this.state.email === "" && this.state.password === "") {
      Alert.alert("Enter details to signup!");
    }
    //If Passwords Dont Match Return Alert
    else if (this.state.password !== this.state.confirmPassword) {
      Alert.alert("Passwords Don't Match");
    }
    //If Everything OK Register User
    else {
      this.setState({
        isLoading: true,
      });
      firebase
        //Activate Auth
        .auth()
        //New Function
        //Create New User
        .createUserWithEmailAndPassword(this.state.email, this.state.password)
        //After Creating User
        .then(() => {
          console.log("User registered successfully!");
          this.setState({
            isLoading: false,
            email: "",
            password: "",
            confirmPassword: "",
          });
          // this.props.navigation.navigate("Next Screen");
        })
        .catch((error) => {
          // Handle Errors here.
          var errorCode = error.code;
          var errorMessage = error.message;
          if (errorCode == "auth/weak-password") {
            alert("The password is too weak.");
          } else if (errorCode == "auth/invalid-email") {
            alert("Email is Invalid");
          } else if (errorCode == "auth/email-already-in-use") {
            alert("Email is Already in use!");
          } else {
            alert(errorMessage);
          }
          console.log(error);
          this.setState({
            isLoading: false,
          });
        });
    }
  };

  render() {
    if (this.state.isLoading) {
      return (
        <View style={styles.preloader}>
          <ActivityIndicator size="large" color="#9E9E9E" />
        </View>
      );
    }
    return (
      <View style={styles.container}>
        <View style={styles.titleContainer}>
          <Text style={styles.title}>
            Create an account and join our studio
          </Text>
        </View>
        <View style={styles.inputsContainer}>
          <RegisterTextBox
            type="email"
            style={styles.emailInput}
            placeholder="Email"
            value={this.state.email}
            onChangeText={(val) => this.updateInputVal(val, "email")}
          />
          <RegisterTextBox
            type="pass"
            style={styles.passwordInput}
            placeholder="Password"
            value={this.state.password}
            onChangeText={(val) => this.updateInputVal(val, "password")}
            maxLength={15}
            secureTextEntry={true}
          />
          <RegisterTextBox
            type="pass"
            style={styles.confirmPasswordInput}
            placeholder="Confirm Password"
            value={this.state.confirmPassword}
            onChangeText={(val) => this.updateInputVal(val, "confirmPassword")}
            maxLength={15}
            secureTextEntry={true}
          />
        </View>
        <View style={styles.buttonContainer}>
          <TouchableOpacity
            style={[
              styles.loginButton,
              { backgroundColor: this.state.buttonColor },
            ]}
            title="Continue"
            onPress={() => this.registerUser()}
          >
            <Text style={styles.loginText}>Continue</Text>
          </TouchableOpacity>
        </View>
      </View>
    );
  }
}

const styles = StyleSheet.create({
  //Views
  container: {
    flex: 1,
    backgroundColor: "#ffffff",
  },
  titleContainer: {
    height: hp(10),
    width: wp(65.2),
    alignItems: "center",
    marginLeft: wp(17.4),
    marginRight: wp(17.4),
    marginTop: hp(17.1),
  },
  inputsContainer: {
    marginTop: hp(7.9),
    alignItems: "center",
  },
  buttonContainer: {
    alignItems: "center",
  },
  //Button
  loginButton: {
    flexDirection: "row",
    marginTop: hp(14),
    alignItems: "center",
    justifyContent: "center",
    borderRadius: 32.5,
    width: wp(78.3),
    height: hp(7.3),
    backgroundColor: "grey",
  },
  //Inputs
  emailInput: {
    height: hp(5.4),
    width: wp(65.2),
    borderBottomColor: "grey",
    borderBottomWidth: 1,
  },
  passwordInput: {
    height: hp(5.4),
    width: wp(65.2),
    borderBottomColor: "grey",
    borderBottomWidth: 1,
  },
  confirmPasswordInput: {
    height: hp(5.4),
    width: wp(65.2),
    borderBottomColor: "grey",
    borderBottomWidth: 1,
  },
  //Title
  title: {
    flex: 1,
    textAlign: "center",
    fontSize: hp(3.8),
  },
  //Loading
  preloader: {
    left: 0,
    right: 0,
    top: 0,
    bottom: 0,
    position: "absolute",
    alignItems: "center",
    justifyContent: "center",
    backgroundColor: "#fff",
  },
});

And here is the Input Component:

import React from "react";
import { View, TextInput, StyleSheet, Text } from "react-native";
import {
  widthPercentageToDP as wp,
  heightPercentageToDP as hp,
} from "react-native-responsive-screen";
import { MaterialCommunityIcons, AntDesign } from "@expo/vector-icons";

class RegisterTextBox extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      isTextFill: false,
      isInputValid: false,
      isFocused: false,
    };
  }
  onBlur() {
    this.setState({ isFocused: false });
  }
  onFocus() {
    this.setState({ isFocused: true });
  }

  onChangeTextEvent = (text) => {
    console.log(text);
    if (text.length > 0) {
      this.setState({
        isTextFill: true,
      });
    } else {
      this.setState({
        isTextFill: false,
      });
    }
    console.log(this.state.isTextFill);
  };

  //Validate Email
  //Validate Pass
  //Change Color of Field according to Validation of Text

  render() {
    const { isFocused } = this.state;
    const {
      value,
      type,
      placeholder,
      onChangeText,
      secureTextEntry,
      viewStyle,
      styleInput,
      eyeIcon = false,
    } = this.props;
    console.log(this.props);
    console.log();

    return (
      <View style={[styles.container, viewStyle]}>
        <TextInput
          style={[styles.main, styleInput]}
          value={value}
          onChangeText={(val) => {
            onChangeText();
            this.onChangeTextEvent(val);
          }}
          onBlur={() => this.onBlur()}
          onFocus={() => this.onFocus()}
          placeholder={placeholder}
          secureTextEntry={secureTextEntry}
          type={type}
        />
        {eyeIcon ? (
          <MaterialCommunityIcons
            name="eye-off"
            size={24}
            color="black"
            style={{ paddingTop: 5, paddingLeft: 5 }}
          />
        ) : (
          <View />
        )}
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    height: hp(5.4),
    width: wp(65.2),
    marginBottom: hp(6.3),
    borderBottomWidth: 1,
    flexDirection: "row",
    justifyContent: "space-between",
  },
  main: {
    flex: 1,
  },
});

export default RegisterTextBox;

I got to the point which you can see in the code, I finally got the onChangeTextEvent function to receive the input value but now my Register is broken I get an Error:

Error: createUserWithEmailAndPassword failed: First argument "email" must be a valid string.

What I want to achieve in the Text Input Component:

Upvotes: 0

Views: 638

Answers (1)

D10S
D10S

Reputation: 1549

Your problem is in the "render" function of "RegisterTextBox".You are inserting the email null value.

Change this:

return (
  <View style={[styles.container, viewStyle]}>
    <TextInput
      style={[styles.main, styleInput]}
      value={value}
      onChangeText={(val) => {
        onChangeText();
        this.onChangeTextEvent(val);
      }}
      onBlur={() => this.onBlur()}
      onFocus={() => this.onFocus()}
      placeholder={placeholder}
      secureTextEntry={secureTextEntry}
      type={type}
    />

to

return (
      <View style={[styles.container, viewStyle]}>
        <TextInput
          style={[styles.main, styleInput]}
          value={value}
          onChangeText={(val) => {
            onChangeText(val);         <---------------- CHANGED
            this.onChangeTextEvent(val);
          }}
          onBlur={() => this.onBlur()}
          onFocus={() => this.onFocus()}
          placeholder={placeholder}
          secureTextEntry={secureTextEntry}
          type={type}
        />

Upvotes: 1

Related Questions