Javascript RN:使用React导航和Firebase进行身份验证

Javascript RN:使用React导航和Firebase进行身份验证,javascript,reactjs,react-native,Javascript,Reactjs,React Native,我正在尝试登录并保存用户。这样,当他再次打开应用程序时,他将登录 我正在使用关于react导航“身份验证流”的指南,并尝试设置firebase身份验证 我创建了一个App.js页面,如下所示: // other imports import AsyncStorage from "@react-native-async-storage/async-storage"; const Stack = createStackNavigator(); const AuthContex

我正在尝试登录并保存用户。这样,当他再次打开应用程序时,他将登录

我正在使用关于react导航“身份验证流”的指南,并尝试设置firebase身份验证

我创建了一个App.js页面,如下所示:

// other imports
import AsyncStorage from "@react-native-async-storage/async-storage";

const Stack = createStackNavigator();

const AuthContext = React.createContext();

export default function App({ navigation }) {
  const [state, dispatch] = React.useReducer(
    (prevState, action) => {
      switch (action.type) {
        case "RESTORE_TOKEN":
          return {
            ...prevState,
            userToken: action.token,
            isLoading: false,
          };
        case "SIGN_IN":
          return {
            ...prevState,
            isSignout: false,
            userToken: action.token,
          };
        case "SIGN_OUT":
          return {
            ...prevState,
            isSignout: true,
            userToken: null,
          };
      }
    },
    {
      isLoading: true,
      isSignout: false,
      userToke: null,
    }
  );

  React.useEffect(() => {
    const boostrapAsync = async () => {
      let userToken;
      try {
        userToken = await AsyncStorage.getItem("userToken");
      } catch (e) {
        console.log("recover token failed.");
      }
      dispatch({ type: "RESTORE_TOKEN", token: userToken });
    };

    boostrapAsync();
  }, []);

  const authContext = React.useMemo(() => ({
    signIn: async (data) => {
      dispatch({ type: "SIGN_IN", token: "momentary-token-see-what-to-insert" });
    },
    signOut: () => dispatch({ type: "SIGN_OUT" }),
    signUp: async (data) => {
      dispatch({ type: "SIGN_IN", token: "momentary-token-see-what-to-insert" });
    },
  }));

  return (
    <NavigationContainer>
    <AuthContext.Provider value={authContext}>
      <Stack.Navigator>
        {state.userToken == null ? (
          <Stack.Screen name="Home"  component={Homepage} />
        ) : (
          <Stack.Screen name="Index" component={Index} />
        )}
          <Stack.Screen name="SignUp" component={Registrazione} />
          <Stack.Screen name="Login" component={Login} />
          </Stack.Navigator>
          </AuthContext.Provider>
    </NavigationContainer>
  );
}
//其他导入
从“@react native async storage/async storage”导入异步存储;
const Stack=createStackNavigator();
const AuthContext=React.createContext();
导出默认函数App({navigation}){
const[state,dispatch]=React.useReducer(
(状态、动作)=>{
开关(动作类型){
案例“还原令牌”:
返回{
…国家,
userToken:action.token,
孤岛加载:false,
};
案例“签到”:
返回{
…国家,
isSignout:错,
userToken:action.token,
};
案例“注销”:
返回{
…国家,
是的,
userToken:null,
};
}
},
{
孤岛加载:是的,
isSignout:错,
userToke:null,
}
);
React.useffect(()=>{
const boostrapAsync=async()=>{
让userToken;
试一试{
userToken=await AsyncStorage.getItem(“userToken”);
}捕获(e){
log(“恢复令牌失败”);
}
分派({type:“RESTORE_TOKEN”,TOKEN:userToken});
};
boostrapAsync();
}, []);
const authContext=React.useMoom(()=>({
登录:异步(数据)=>{
分派({type:“SIGN_IN”,token:“瞬时token see what to insert”});
},
签出:()=>dispatch({type:“SIGN_OUT”}),
注册:异步(数据)=>{
分派({type:“SIGN_IN”,token:“瞬时token see what to insert”});
},
}));
返回(
{state.userToken==null(
) : (
)}
);
}
因此,如果用户已经登录,我会在索引中重定向,如果用户没有登录,我会在家中重定向

在家里,我有两个按钮可以注册

在登录页面中:

export default function Login({navigation}) {
const [ email, setEmail ] = useState('');
const [ password, setPassword ] = useState('');


const onLoginPress = () => {
    firebase
    .auth()
    .signInWithEmailAndPassword(email, password)
    .then((response) => {
        console.log('response: ', response)
        const uid = response.user.uid
        const usersRef = firebase.firestore().collection('users')
        usersRef
        .doc(uid)
        .get()
        .then(firestoreDocument => {
            if(!firestoreDocument.exists) {
                alert('User doesn't exist)
                return;
            }
            const user = firestoreDocument.data()
            let AuthContext = user
            const { signIn }  = useContext(AuthContext)
            navigation.navigate('Index', {user})
        })
        .catch(error => {
            console.log('login error ', error)
        });
    })
    .catch(error => {
        alert(error)
    })
}



return(
<View>
  <TextInput
    placeholder="Username"
    value={email}
    onChangeText={setEmail}
  />
  <TextInput
    placeholder="Password"
    value={password}
    onChangeText={setPassword}
    secureTextEntry
  />
  <TouchableOpacity  onPress={() => onLoginPress()}><Text>LOGIN</Text></TouchableOpacity>
</View>
);
导出默认函数登录({navigation}){
const[email,setEmail]=useState(“”);
const[password,setPassword]=useState(“”);
const onLoginPress=()=>{
火基
.auth()
.使用电子邮件和密码登录(电子邮件、密码)
。然后((响应)=>{
console.log('响应:',响应)
const uid=response.user.uid
const usersRef=firebase.firestore().collection('users')
usersRef
.doc(uid)
.get()
。然后(firestoreDocument=>{
如果(!firestoreDocument.exists){
警报('用户不存在)
返回;
}
const user=firestoreDocument.data()
让AuthContext=user
const{signIn}=useContext(AuthContext)
navigation.navigate('Index',{user})
})
.catch(错误=>{
console.log('login error',error)
});
})
.catch(错误=>{
警报(错误)
})
}
返回(
onLoginPress()}>LOGIN
);
}

问题在于,我应该检查用户是否存在,然后尝试在AuthContext中保存用户,然后重定向到索引

我该怎么办

通过这种方式,我收到:

登录错误:钩子调用无效 钩子只能在函数组件的主体内部调用。 这可能是由于以下原因之一:

  • React和渲染器的版本可能不匹配(例如React DOM)
  • 你可能违反了钩子的规则
  • 同一应用程序中可能有多个React副本