Hi there i am trying to build an app with firebase authentication. in my signup screen once everything is inserted and validated i press my button "register" and i get thi error TypeError: props.handler is not a function This is my code for the signup screen
Signup.js
import { StatusBar } from 'expo-status-bar';
import React, { useEffect, useState } from 'react'
import { StyleSheet, Text, View, TouchableOpacity } from 'react-native';
import { Input, NativeBaseProvider, Button, Icon, Box, Image, AspectRatio } from 'native-base';
import { FontAwesome5 } from '@expo/vector-icons';
import { useNavigation } from '@react-navigation/native';
import { alignContent, flex, flexDirection, width } from 'styled-system';
export function Signin(props) {
const navigation = useNavigation();
const [email,setEmail] = useState()
const [password, setPassword] = useState()
useEffect( () => {
if( props.auth === true ) {
navigation.reset({ index: 0, routes: [ {name: 'Home'} ] })
}
}, [props.auth] )
return (
<View style={styles.container}>
<View style={styles.Middle}>
<Text style={styles.LoginText}>Login</Text>
</View>
<View style={styles.text2}>
<Text>Don't have an account? </Text>
<TouchableOpacity onPress={() => navigation.navigate("Signup")} ><Text style={styles.signupText}> Sign up</Text></TouchableOpacity>
</View>
{/* Username or Email Input Field */}
<View style={styles.buttonStyle}>
<View style={styles.emailInput}>
<Input
InputLeftElement={
<Icon
as={<FontAwesome5 name="user-secret" />}
size="sm"
m={2}
_light={{
color: "black",
}}
_dark={{
color: "gray.300",
}}
/>
}
variant="outline"
onChangeText={ (val) => setEmail(val) }
placeholder="Username or Email"
_light={{
placeholderTextColor: "blueGray.400",
}}
_dark={{
placeholderTextColor: "blueGray.50",
}}
/>
</View>
</View>
{/* Password Input Field */}
<View style={styles.buttonStyleX}>
<View style={styles.emailInput}>
<Input
InputLeftElement={
<Icon
as={<FontAwesome5 name="key" />}
size="sm"
m={2}
_light={{
color: "black",
}}
_dark={{
color: "gray.300",
}}
/>
}
variant="outline"
onChangeText={ (val) => setPassword(val) }
secureTextEntry={true}
placeholder="Password"
_light={{
placeholderTextColor: "blueGray.400",
}}
_dark={{
placeholderTextColor: "blueGray.50",
}}
/>
</View>
</View>
{/* Button */}
<View style={styles.buttonStyle}>
<Button style={styles.buttonDesign}
onPress={ () => { props.handler(username, email,password) }}>
LOGIN
</Button>
</View>
{/* Line */}
<View style={styles.lineStyle}>
<View style={{flex: 1, height: 1, backgroundColor: 'black'}} />
<View>
<Text style={{width: 50, textAlign: 'center'}}>Or</Text>
</View>
<View style={{flex: 1, height: 1, backgroundColor: 'black'}} />
</View>
{/* Box */}
<View style={styles.boxStyle}>
<Box
onPress={() => navigation.navigate("#")} // for navigation
style={{height:80, width:80}}
shadow={3}
_light={{
backgroundColor: "gray.50",
}}
_dark={{
backgroundColor: "gray.700",
}}
>
<AspectRatio ratio={1 / 1}>
<Image
roundedTop="lg"
source={{
uri: "https://www.transparentpng.com/thumb/google-logo/colorful-google-logo-transparent-clipart-download-u3DWLj.png",
}}
alt="image"
/>
</AspectRatio>
</Box>
<Box
onPress={() => navigation.navigate("#")} // for navigation
style={styles.imageStyle}
shadow={3}
_light={{
backgroundColor: "gray.50",
}}
_dark={{
backgroundColor: "gray.700",
}}
>
<AspectRatio ratio={1 / 1}>
<Image
roundedTop="lg"
source={{
uri: "https://www.transparentpng.com/thumb/facebook-logo-png/photo-facebook-logo-png-hd-25.png",
}}
alt="image"
/>
</AspectRatio>
</Box>
<Box
onPress={() => navigation.navigate("#")} // for navigation
style={styles.imageStyle}
shadow={3}
_light={{
backgroundColor: "gray.50",
}}
_dark={{
backgroundColor: "gray.700",
}}
>
<AspectRatio ratio={1 / 1}>
<Image
roundedTop="lg"
source={{
uri: "https://www.transparentpng.com/thumb/twitter/bird-twitter-socialmedia-icons-png-5.png",
}}
alt="image"
/>
</AspectRatio>
</Box>
<Box
onPress={() => navigation.navigate("#")} // for navigation
style={styles.imageStyle}
shadow={3}
_light={{
backgroundColor: "gray.50",
}}
_dark={{
backgroundColor: "gray.700",
}}
>
<AspectRatio ratio={1 / 1}>
<Image
roundedTop="lg"
source={{
uri: "https://www.transparentpng.com/thumb/apple-logo/RRgURB-apple-logo-clipart-hd.png",
}}
alt="image"
/>
</AspectRatio>
</Box>
</View>
<StatusBar style="auto" />
</View>
);
}
export default () => {
return (
<NativeBaseProvider>
<Signin />
</NativeBaseProvider>
)
}
And this is my code for the App.js App.js
import { StatusBar } from 'expo-status-bar';
import React, { useState, useEffect } from 'react';
import { StyleSheet, Text, View } from 'react-native';
import { createNativeStackNavigator } from '@react-navigation/native-stack';
// components
import Signup from './components/Signup'
import Signin from './components/Signin'
import Home from './components/Home';
import { NavigationContainer } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';
// firebase
import { firebaseConfig } from './Config';
import {initializeApp,} from 'firebase/app'
import { getAuth, createUserWithEmailAndPassword, onAuthStateChanged, signInWithEmailAndPassword, signOut } from "firebase/auth"
import {
initializeFirestore,
getFirestore,
setDoc,
doc,
addDoc,
collection,
query,
where,
onSnapshot
} from 'firebase/firestore'
const FBapp = initializeApp( firebaseConfig)
const FSdb = initializeFirestore(FBapp, {useFetchStreams: false})
const FBauth = getAuth()
initializeApp(firebaseConfig)
const Stack = createStackNavigator();
function App() {
const[ auth, setAuth ] = useState()
const[ user, setUser ] = useState()
const [signupError, setSignupError ] = useState()
const [signinError, setSigninError ] = useState()
const [ data, setData ] = useState()
useEffect(() => {
onAuthStateChanged( FBauth, (user) => {
if( user ) {
setAuth(true)
setUser(user)
// console.log( 'authed')
if( !data ) { getData() }
}
else {
setAuth(false)
setUser(null)
}
})
})
// useEffect( () => {
// if( !data && user ) {
// getData()
// }
// }, [data,auth, user])
const SignupHandler = ( email, password ) => {
setSignupError(null)
createUserWithEmailAndPassword( FBauth, email, password )
.then( ( userCredential ) => {
setUser(userCredential.user)
setAuth( true )
} )
.catch( (error) => { setSignupError(error.code) })
}
const SigninHandler = ( email, password ) => {
signInWithEmailAndPassword( FBauth, email, password )
.then( (userCredential) => {
setUser(userCredential.user)
setAuth(true)
console.log( userCredential.user.uid)
})
.catch( (error) => {
const message = (error.code.includes('/') ) ? error.code.split('/')[1].replace(/-/g, ' ') : error.code
setSigninError(message)
})
}
return (
<Stack.Navigator screenOptions={{headerShown: false}} >
<Stack.Screen name="Signup" options={{title: 'Sign up'}}>
{ (props) =>
<Signup {...props}
handler={SignupHandler}
auth={auth}
error={signupError}
/> }
</Stack.Screen>
<Stack.Screen
name="Signin"
options={{
title:'Sign in'
}}
>
{ (props) =>
<Signin {...props}
auth={auth}
error={signinError}
handler={SigninHandler}
/> }
</Stack.Screen>
<Stack.Screen name="Home" options={{
headerTitle: "Home",
headerRight: (props) => <Signout {...props} handler={SignoutHandler} user={user}/>
}}>
{ (props) =>
<Home {...props} auth={auth} add={addData} data={ data } /> }
</Stack.Screen>
</Stack.Navigator>
);
}
export default () => {
return (
<NavigationContainer>
<App />
</NavigationContainer>
)
}
CodePudding user response:
In Signup.js, you define the component Signin which takes props as argument. Then you export a new component which renders a Signin component wrapped by a NativeBaseProvider:
export default () => {
return (
<NativeBaseProvider>
<Signin />
</NativeBaseProvider>
)
}
But this exported component doesn't forward any props. That's why you get this error when you try to call props.handler in the Signin component.
You have to pass on props in the export:
export default (props) => {
return (
<NativeBaseProvider>
<Signin {...props} />
</NativeBaseProvider>
)
}