Javascript 如何在react navigation 5身份验证流中实现firebase身份验证?
我正在尝试添加firebase身份验证,以便在我的应用程序中注册、登录和注销。我遵循react导航网站的代码结构。这是上下文文件Javascript 如何在react navigation 5身份验证流中实现firebase身份验证?,javascript,react-native,Javascript,React Native,我正在尝试添加firebase身份验证,以便在我的应用程序中注册、登录和注销。我遵循react导航网站的代码结构。这是上下文文件 import React from 'react'; export const AuthContext = React.createContext(); 这是我的应用程序文件。对于登录,我使用电子邮件和密码。对于注册,我想添加电子邮件、用户名和密码 import React, { useContext, useState, useReducer, useEffec
import React from 'react';
export const AuthContext = React.createContext();
这是我的应用程序文件。对于登录,我使用电子邮件和密码。对于注册,我想添加电子邮件、用户名和密码
import React, { useContext, useState, useReducer, useEffect, useMemo } from 'react';
import { Home, Profile, Settings, Chat, Phone } from "./src/screens";
import {
NavigationContainer,
DefaultTheme as NavigationDefaultTheme,
DarkTheme as NavigationDarkTheme
} from '@react-navigation/native';
import {
Provider as PaperProvider,
DefaultTheme as PaperDefaultTheme,
DarkTheme as PaperDarkTheme
} from 'react-native-paper';
import { createDrawerNavigator } from '@react-navigation/drawer';
import AsyncStorage from '@react-native-community/async-storage';
import Fire from './src/api/Fire';
import firebase from 'firebase';
import AppTabs from "./src/stacks/AppTabs";
import AuthStack from "./src/stacks/AuthStack";
import { DrawerContent } from "./src/screens/DrawerContent";
import Spinner from "./src/components/Spinner";
import { AuthContext } from './src/components/Context';
const Drawer = createDrawerNavigator();
export default function App() {
const [isDarkTheme, setIsDarkTheme] = useState(false);
{/* Themes */ }
const CustomDefaultTheme = {
...NavigationDefaultTheme,
...PaperDefaultTheme,
colors: {
...NavigationDefaultTheme.colors,
...PaperDefaultTheme.colors,
background: '#ffffff',
text: '#333333'
}
}
const CustomDarkTheme = {
...NavigationDarkTheme,
...PaperDarkTheme,
colors: {
...NavigationDarkTheme.colors,
...PaperDarkTheme.colors,
background: '#333333',
text: '#ffffff'
}
}
const theme = isDarkTheme ? CustomDarkTheme : CustomDefaultTheme;
const [state, dispatch] = useReducer(
(prevState, action) => {
switch (action.type) {
case 'RESTORE_TOKEN':
return {
...prevState,
userToken: action.token,
isLoading: false,
};
case 'SIGN_IN':
return {
...prevState,
email: action.id,
isSignout: false,
userToken: action.token,
isLoading: false,
};
case 'SIGN_OUT':
return {
...prevState,
email: null,
isSignout: true,
userToken: null,
isLoading: false,
};
case 'REGISTER':
return {
...prevState,
email: action.id,
isLoading: false,
userToken: action.token,
};
}
},
{
isLoading: true,
isSignout: false,
email: null,
userToken: null,
}
);
const authContext = useMemo(() => ({
signIn: async data => {
// In a production app, we need to send some data (usually username, password) to server and get a token
// We will also need to handle errors if sign in failed
// After getting token, we need to persist the token using `AsyncStorage`
// In the example, we'll use a dummy token
dispatch({ type: 'SIGN_IN', id: email, token: userToken });
},
signOut: async data => {
dispatch({ type: 'SIGN_OUT' })
},
signUp: async data => {
// In a production app, we need to send user data to the server and get a token
// We will also need to handle errors if sign up failed
// After getting token, we need to persist the token using `AsyncStorage`
// In the example, we'll use a dummy token
dispatch({ type: 'REGISTER', id: email, token: userToken });
},
toggleTheme: () => {
setIsDarkTheme(isDarkTheme => !isDarkTheme);
}
}),
[]
);
useEffect(() => {
setTimeout(async () => {
let userToken;
userToken = null;
try {
userToken = await AsyncStorage.getItem('userToken');
} catch (e) {
console.log(e);
}
dispatch({ type: 'RESTORE_TOKEN', token: userToken });
}, 1000);
}, []);
if (state.isLoading) {
return (
<Spinner />
);
}
return (
<PaperProvider theme={theme}>
<AuthContext.Provider value={authContext}>
<NavigationContainer theme={theme}>
{state.userToken !== null ? (
<Drawer.Navigator drawerContent={props => <DrawerContent {...props} />} >
<Drawer.Screen name="HomeDrawer" component={AppTabs} />
<Drawer.Screen name="ProfileDrawer" component={Profile} />
<Drawer.Screen name="SettingsDrawer" component={Settings} />
<Drawer.Screen name="PhoneDrawer" component={Phone} />
</Drawer.Navigator>
)
:
<AuthStack />
}
</NavigationContainer>
</AuthContext.Provider>
</PaperProvider>
)
}
我见过一些将FirebaseAuth包装在NavigationContainer
周围的代码,AuthContext.Provider
不会做同样的事情吗
我正在使用useContext
在各自的屏幕上调用SingIn
和SignUp
,如下所示
const { signUp } = useContext(AuthContext); // signup screen
const { signIn } = useContext(AuthContext); // signin screen
然后在onPress函数中使用它们,比如
onPress={()=>{signUp(email,username,paswword)}
我从这个链接中得到了一个想法:
对于useReducer钩子
const [state, dispatch] = useReducer(
(prevState, action) => {
switch (action.type) {
case 'RESTORE_TOKEN':
return {
...prevState,
user: action.payload.user,
userToken: action.token,
isLoading: false,
};
case 'SIGN_IN':
return {
...prevState,
user: action.payload.user,
isSignout: false,
userToken: action.token,
isLoading: false,
};
case 'SIGN_OUT':
return {
...prevState,
user: null,
isSignout: true,
userToken: null,
isLoading: false,
};
case 'REGISTER':
return {
...prevState,
isLoading: false,
};
default:
throw new Error(`No case for type ${action.type} found.`)
}
},
{
isLoading: true,
isSignout: false,
userToken: null,
user: null,
}
);
authContext
function getRef() {
return firebase.database().ref();
}
const authContext = useMemo(() => ({
signIn: async (email, password, user) => {
await firebase.auth().signInWithEmailAndPassword(email.trim(), password)
.then(() => {
state.isLoading = false
})
.catch(function (error) {
// Handle Errors here.
const errorCode = error.code
const errorMessage = error.message
alert(errorMessage)
state.isLoading = false
})
dispatch({
type: 'SIGN_IN',
payload: {
user: firebase.auth().currentUser,
},
});
},
signOut: async () => {
firebase.auth().signOut()
.then(function () {
// Sign-out successful.
state.isLoading = false
})
.catch(function (error) {
// An error happened.
state.isLoading = false
})
dispatch({ type: 'SIGN_OUT' })
},
signUp: async (email, password, avatar, displayName, phoneNumber, about) => {
try {
await firebase.auth().createUserWithEmailAndPassword(email.trim(), password)
.then((userInfo) => {
userInfo.user.updateProfile({
displayName: displayName,
photoURL: avatar,
phoneNumber: phoneNumber,
})
console.log(userInfo);
})
.then(() => {
firebase.auth().onAuthStateChanged(user => {
getRef().child('users')
.push({
avatar: avatar,
email: email,
name: displayName,
phoneNumber: phoneNumber,
aboutMe: about,
uid: user.uid
})
})
})
}
catch (error) {
alert(error);
}
dispatch({
type: 'REGISTER'
})
},
toggleTheme: () => {
setIsDarkTheme(isDarkTheme => !isDarkTheme);
}
}),
[]
);
效用钩
useEffect(() => {
setTimeout(async () => {
firebase.auth().onAuthStateChanged(function (user) {
if (user) {
// User is signed in.
if (onAuthStateChange.current) {
onAuthStateChange.current = false
return
}
dispatch({
type: 'RESTORE_TOKEN',
payload: {
user,
},
})
} else {
// User is signed out.
dispatch({
type: 'SIGN_OUT',
payload: {
user: null,
},
})
}
})
}, 1000);
}, []);
和返回函数
return (
<PaperProvider theme={theme}>
<AuthContext.Provider value={authContext}>
<NavigationContainer
theme={theme}
>
{state.user !== null ? (
<Drawer.Navigator drawerContent={props => <DrawerContent {...props} />} >
<Drawer.Screen name="HomeDrawer" component={AppTabs} />
<Drawer.Screen name="ProfileDrawer" component={Profile} />
<Drawer.Screen name="SettingsDrawer" component={Settings} />
<Drawer.Screen name="PhoneDrawer" component={Phone} />
</Drawer.Navigator>
)
:
<AuthStack />
}
</NavigationContainer>
</AuthContext.Provider>
</PaperProvider>
)
返回(
{state.user!==null(
} >
)
:
}
)
如果您注意到某些东西使用不当,请告知。否则,这就是目前对我有效的方法。即使在应用程序重新启动后,我仍在尝试在主题更改时保持其状态。你找到答案了吗?是的。我所做的似乎对我有用。你能发布你的解决方案的代码片段吗?@Jesse,我从这个链接中得到了一个想法:我已经给出了下面这个问题的答案。
return (
<PaperProvider theme={theme}>
<AuthContext.Provider value={authContext}>
<NavigationContainer
theme={theme}
>
{state.user !== null ? (
<Drawer.Navigator drawerContent={props => <DrawerContent {...props} />} >
<Drawer.Screen name="HomeDrawer" component={AppTabs} />
<Drawer.Screen name="ProfileDrawer" component={Profile} />
<Drawer.Screen name="SettingsDrawer" component={Settings} />
<Drawer.Screen name="PhoneDrawer" component={Phone} />
</Drawer.Navigator>
)
:
<AuthStack />
}
</NavigationContainer>
</AuthContext.Provider>
</PaperProvider>
)