TypeError: props.handler is not a function
TypeError: props.handler is not a function
您好,我正在尝试使用 firebase 身份验证构建一个应用程序。
在我的注册屏幕上,一旦所有内容都被插入并验证,我按下我的按钮“注册”,我得到了这个错误
类型错误:props.handler 不是一个函数
这是我的注册屏幕代码
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>
)
}
这是我的 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>
)
}
在Signup.js中,您定义了组件Signin,它将props作为参数。
然后导出一个新组件,该组件呈现由 NativeBaseProvider 包装的 Signin 组件:
export default () => {
return (
<NativeBaseProvider>
<Signin />
</NativeBaseProvider>
)
}
但是这个导出的组件没有转发任何道具。这就是当您尝试在登录组件中调用 props.handler 时出现此错误的原因。
你必须在导出中传递道具:
export default (props) => {
return (
<NativeBaseProvider>
<Signin {...props} />
</NativeBaseProvider>
)
}
您好,我正在尝试使用 firebase 身份验证构建一个应用程序。 在我的注册屏幕上,一旦所有内容都被插入并验证,我按下我的按钮“注册”,我得到了这个错误 类型错误:props.handler 不是一个函数 这是我的注册屏幕代码
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>
)
}
这是我的 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>
)
}
在Signup.js中,您定义了组件Signin,它将props作为参数。 然后导出一个新组件,该组件呈现由 NativeBaseProvider 包装的 Signin 组件:
export default () => {
return (
<NativeBaseProvider>
<Signin />
</NativeBaseProvider>
)
}
但是这个导出的组件没有转发任何道具。这就是当您尝试在登录组件中调用 props.handler 时出现此错误的原因。
你必须在导出中传递道具:
export default (props) => {
return (
<NativeBaseProvider>
<Signin {...props} />
</NativeBaseProvider>
)
}