Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/react-native/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如何在react navigation 5身份验证流中实现firebase身份验证?_Javascript_React Native - Fatal编程技术网

Javascript 如何在react navigation 5身份验证流中实现firebase身份验证?

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

我正在尝试添加firebase身份验证,以便在我的应用程序中注册、登录和注销。我遵循react导航网站的代码结构。这是上下文文件

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>
  )