我正在尝试添加Firebase身份以进行注册,登录和退出我的应用程序。我遵循了react-navigation网站上的代码结构。这是上下文文件...
import React from 'react';
export const AuthContext = React.createContext();
这是我的App文件。对于登录,我使用的是电子邮件和密码。对于注册,我想添加电子邮件,用户名和密码。
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>
)
}
firebase API密钥已在此导入文件中初始化。
import Fire from './src/api/Fire';
我已经看到一些将FirebaseAuth封装在NavigationContainer
周围的代码,AuthContext.Provider
不会做同样的事情吗?
我正在使用SingIn
在其各自的屏幕上呼叫SignUp
和useContext
,像这样
const { signUp } = useContext(AuthContext); // signup screen
const { signIn } = useContext(AuthContext); // signin screen
然后在onPress={()=>{signUp(email, username, paswword)}}
之类的onPress函数中使用它们
答案 0 :(得分:1)
从这个链接中我发现应该做什么:use-auth
对于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挂钩
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>
)
如果您发现使用不正确的物品,请提出建议。否则,这就是目前对我有用的东西。即使更改了应用程序,我仍在尝试更改主题时保持其状态。