Search code examples
react-nativeinputref

Pass Input value to parent component function


I'm trying to develop a react-native APP.
I'm very experienced with Java & PHP, but something is puzzling me with react-native.
Basically, I'm trying to obtain a working Login PAGE (just for practical exercise) but I'm struggling when I try to pass value from child component value (for example, the Password Input) to parent component function (the LoginForm).

Here's a specific code: [PasswordInput]

import * as React from 'react';
import { View } from 'react-native';
import { HelperText, TextInput } from 'react-native-paper';

class PasswordInput extends React.Component {
    constructor(props){
        super(props);
        this.state ={
            password:''
        };
    }
    getPassword() {
        return this.state.password;
    }

    login(){
        alert(this.state.password)
    }

    OnChangesValue(e){
        console.log(e.nativeEvent.text);
        this.setState({
            userName :e.nativeEvent.text,
        })
    }

    changePassword(e){
        console.log(e.nativeEvent.text);
        this.setState({
            password :e.nativeEvent.text,
        })
    }

    hasErrors(text){
        let result=true;
        if(text.length>10 || text.length==0){
            result=false;
        }
        return result;
    };

    render() {
        return (
            <View>
                <TextInput
                    ref="pass"
                    name="password"
                    onChange={this.changePassword.bind(this)}
                    secureTextEntry={true}
                    label="Password"
                    left={<TextInput.Icon name="lock" onPress={() => {
                    }}/>}
                />
                <HelperText type="error" visible={this.hasErrors(this.state.password)}>
                    Password too short!
                </HelperText>
            </View>
        );
    }
}

export default PasswordInput;

and here the LoginForm component:

import * as React from 'react';
import { Component, createRef } from "react";
import {View, StyleSheet} from 'react-native';
import {Button, Card, Title} from 'react-native-paper';
import EmailInput from './login_components/email_input';
import PasswordInput from './login_components/password_input';
import {useRef} from 'react/cjs/react.production.min';

class LoginForm extends React.Component {

    passwordInput = createRef();

    submitForm(){
        alert(this.passwordInput['password'].value);
    }

    render() {
        return (
            <Card style={styles.detailRowContainer}>
                <Card.Title
                    title="Signup!"
                    subtitle="Inserisci i tuoi dati per eseguire il login"
                />
                <EmailInput/>
                <PasswordInput ref={this.passwordInput}/>
                <Card.Actions>
                    <Button mode="contained" type="submit" style={styles.loginButtonSection} onPress={() => this.submitForm()}>
                        LOGIN
                    </Button>
                </Card.Actions>
            </Card>
        );
    }
}

const styles = StyleSheet.create({
    loginButtonSection: {
        width: '100%',
        height: '30%',
        justifyContent: 'center',
        alignItems: 'center'
    },
    detailRowContainer: {
        flex:1,
        flexDirection:'row',
        alignItems:'center',
        justifyContent:'center'
    },
});
export default LoginForm;

My goal (for now) is to understand how to receive the PasswordInput value in my LoginForm component in order to print the password in the alert (submitForm() function).


Solution

  • Perhaps easier would be to go about it in the opposite direction and have a reusable component which is given props to alter its appearance and functionality.

    Landing page:

    // importing Input.tsx from folder: components
    import Input from '../components/Input';
    
    export default function LandingScreen() {
      // Hooks for email and password
      const [email, set_email] = useState<string>('');
      const [password, set_password] = useState<string>('');
    
    return(
           <View>
                <Input
                  placeholder="Email"
                  onChangeText={(text) => set_email(text)}
                  keyboardType="email-address"
                />
                <Input
                  placeholder="Password"
                  onChangeText={(text) => set_password(text)}
                  secureTextEntry={true}
                  keyboardType="default"
                />
           </View>
    )
    

    Here is an example of an Input component: (so instead of passing information from an child to parent we now have a reusable component which accepts a few props defined in its interface).

    imported Input.tsx found in folder: components

    import React, { FC } from 'react';
    import { View, StyleSheet, useWindowDimensions } from 'react-native';
    import { TextInput } from 'react-native-gesture-handler';
    
    interface Props {
      placeholder: string;
      onChangeText: (text: string) => void;
      secureTextEntry?: boolean;
      keyboardType: any;
    }
    
    const Input: FC<Props> = (props) => {
      const { width } = useWindowDimensions();
      return (
        <View style={styles.container}>
          <TextInput
            style={[styles.input, { width: width * 0.8 }]}
            autoCapitalize={'none'}
            placeholder={props.placeholder}
            secureTextEntry={props.secureTextEntry}
            onChangeText={props.onChangeText}
            keyboardType={props.keyboardType}
            placeholderTextColor={'black'}
          />
        </View>
      );
    };
    
    export default Input;
    
    const styles = StyleSheet.create({
      container: {
        alignSelf: 'center',
        backgroundColor: '#e3e3e3',
        borderRadius: 5,
        marginVertical: 10,
      },
      input: {
        padding: 15,
      },
    });
    

    A great way to get started with a sign-in screen is with "formik" and "yup" which enables quick creation of input fields and client-side validation with hooks.