我已经实现了领域设备同步,并且我正在使用电子邮件/密码身份验证方法来登录。我按照模板中提供的步骤进行操作,并将导航容器放置在 Realm 的 AppProvider 和 User Provider 组件的顶层。当用户未登录时,我将显示登录页面。但是,我无法移动到从登录页面导航的注册页面。
App.tsx 代码
import "react-native-gesture-handler";
import { NavigationContainer } from "@react-navigation/native";
import { GestureHandlerRootView } from "react-native-gesture-handler";
import NativeStack from "./src/routes/NativeStack";
import { SafeAreaProvider } from "react-native-safe-area-context";
import { PaperProvider } from "react-native-paper";
import { AppProvider, UserProvider } from "@realm/react";
import { appId, baseUrl } from "./atlasConfig.json";
import Login from "./src/screens/authScreen/Login";
import realmContext from "./src/data/dbContext";
import Loading from "./src/screens/loadingScreen/Loading";
export default function App() {
// Getting Realm Provider
const { RealmProvider } = realmContext;
return (
<PaperProvider>
<SafeAreaProvider>
<GestureHandlerRootView style={{ flex: 1 }}>
<NavigationContainer>
<AppProvider id={appId} baseUrl={baseUrl}>
<UserProvider fallback={Login}>
<RealmProvider
sync={{
flexible: true,
onError: (_, error) => {
console.log(error);
},
initialSubscriptions: {
update(subs, realm) {
subs.add(realm.objects("Company")),
subs.add(realm.objects("Purchase")),
subs.add(realm.objects("Payment"));
},
},
}}
fallback={Loading}
>
<NativeStack />
</RealmProvider>
</UserProvider>
</AppProvider>
</NavigationContainer>
</GestureHandlerRootView>
</SafeAreaProvider>
</PaperProvider>
);
}
Login.tsx 代码
import Realm from "realm";
import {
Keyboard,
NativeSyntheticEvent,
StyleSheet,
TextInputChangeEventData,
TouchableWithoutFeedback,
View,
} from "react-native";
import React, { useCallback, useState } from "react";
import { StackActions, useNavigation } from "@react-navigation/native";
import { SafeAreaView } from "react-native-safe-area-context";
import { Button, Text, TextInput } from "react-native-paper";
import { useApp } from "@realm/react";
const Login = () => {
// Realm App Context
const app = useApp();
// Navigation
const nav = useNavigation();
// Form input variables
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
// Toggle Password Visibility
const [passwordVisibility, setPasswordVisibility] = useState(true);
// Action Handlers
const formClear = () => {
setEmail("");
setPassword("");
setPasswordVisibility(true);
};
const registerHandler = () => {
nav.dispatch(StackActions.replace("Register"));
formClear();
};
const loginHandler = useCallback(async () => {
const creds = Realm.Credentials.emailPassword({ email, password });
await app.logIn(creds);
formClear();
}, [app, email, password]);
return (
<TouchableWithoutFeedback
onPress={Keyboard.dismiss}
style={styles.containerWrapper}
>
<SafeAreaView style={styles.containerWrapper}>
<View style={styles.container}>
<View style={styles.headerContainer}>
<Text variant="titleLarge" style={styles.headerLabel}>
Register
</Text>
</View>
<View>
<TextInput
label="Email"
placeholder="Email"
value={email}
autoCapitalize="none"
onChange={(e: NativeSyntheticEvent<TextInputChangeEventData>) => {
setEmail(e.nativeEvent.text);
}}
/>
<TextInput
label="Password"
placeholder="Password"
value={password}
autoCapitalize="none"
secureTextEntry={passwordVisibility}
onChange={(e: NativeSyntheticEvent<TextInputChangeEventData>) => {
setPassword(e.nativeEvent.text);
}}
right={
<TextInput.Icon
icon="eye"
onPress={() => {
setPasswordVisibility((previousState) => !previousState);
}}
/>
}
/>
</View>
<View style={styles.buttonContainer}>
<Button mode="contained" onPress={loginHandler}>
Login
</Button>
<Button mode="outlined" onPress={registerHandler}>
Don't have an Account? Register
</Button>
</View>
</View>
</SafeAreaView>
</TouchableWithoutFeedback>
);
};
export default Login;
const styles = StyleSheet.create({
containerWrapper: {
flex: 1,
},
container: {
flex: 1,
},
headerContainer: {},
headerLabel: {},
inputContainer: {
gap: 20,
},
buttonContainer: {},
button: {},
});
Signup.tsx 代码
import Realm from "realm";
import {
Alert,
Keyboard,
NativeSyntheticEvent,
StyleSheet,
TextInputChangeEventData,
TouchableWithoutFeedback,
View,
} from "react-native";
import React, { useCallback, useState } from "react";
import { SafeAreaView } from "react-native-safe-area-context";
import { Button, Text, TextInput } from "react-native-paper";
import { StackActions, useNavigation } from "@react-navigation/native";
import { useApp } from "@realm/react";
const Register = () => {
// App Context for Realm
const app = useApp();
// Navigation
const nav = useNavigation();
// Form input variables
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [confirmPassword, setConfirmPassword] = useState("");
// Toggle Password Visibility
const [passwordVisibility, setPasswordVisibility] = useState(true);
const [confirmPasswordVisibility, setConfirmPasswordVisibility] =
useState(true);
// Action Handlers
const formClear = () => {
setEmail("");
setPassword("");
setConfirmPassword("");
setPasswordVisibility(true);
setConfirmPasswordVisibility(true);
};
const signIn = useCallback(async () => {
const creds = Realm.Credentials.emailPassword({ email, password });
await app.logIn(creds);
}, [app, email, password]);
const registerHandler = useCallback(async () => {
try {
await app.emailPasswordAuth.registerUser({ email, password });
await signIn();
formClear();
} catch (error: any) {
Alert.alert(`Failed to Register: ${error?.message}`);
}
}, [signIn, app, email, password]);
const loginHandler = () => {
nav.dispatch(StackActions.replace("Login"));
formClear();
};
return (
<TouchableWithoutFeedback
onPress={Keyboard.dismiss}
style={styles.containerWrapper}
>
<SafeAreaView style={styles.containerWrapper}>
<View style={styles.container}>
<View style={styles.headerContainer}>
<Text variant="displayLarge" style={styles.headerLabel}>
Register
</Text>
</View>
<View style={styles.formContainer}>
<TextInput
label="Email"
placeholder="Email"
value={email}
autoCapitalize="none"
onChange={(e: NativeSyntheticEvent<TextInputChangeEventData>) => {
setEmail(e.nativeEvent.text);
}}
/>
<TextInput
label="Password"
placeholder="Password"
value={password}
autoCapitalize="none"
secureTextEntry={passwordVisibility}
onChange={(e: NativeSyntheticEvent<TextInputChangeEventData>) => {
setPassword(e.nativeEvent.text);
}}
right={
<TextInput.Icon
icon="eye"
onPress={() => {
setPasswordVisibility((previousState) => !previousState);
}}
/>
}
/>
<TextInput
label="Confirm Password"
placeholder="Re-Enter Password"
value={confirmPassword}
autoCapitalize="none"
secureTextEntry={confirmPasswordVisibility}
onChange={(e: NativeSyntheticEvent<TextInputChangeEventData>) => {
setConfirmPassword(e.nativeEvent.text);
}}
right={
<TextInput.Icon
icon="eye"
onPress={() => {
setConfirmPasswordVisibility(
(previousState) => !previousState
);
}}
/>
}
/>
</View>
<View style={styles.buttonContainer}>
<Button mode="contained" onPress={registerHandler}>
Register
</Button>
<Button mode="outlined" onPress={loginHandler}>
Already have an Account? Login
</Button>
</View>
</View>
</SafeAreaView>
</TouchableWithoutFeedback>
);
};
export default Register;
const styles = StyleSheet.create({
containerWrapper: {
flex: 1,
},
container: {
flex: 1,
},
headerContainer: {
height: 80,
},
headerLabel: {},
inputContainer: {
gap: 20,
},
buttonContainer: {},
button: {},
formContainer: {
flex: 1,
gap: 20,
},
});
我尝试将导航容器移至领域提供程序和应用程序提供程序上方,以查看是否在之后提供了导航对象。目前还没有解决方案。
我稍后会发布这个答案。回退下 Realm 的 UserProvider 需要单独的导航堆栈设置,因此我遇到了未初始化导航对象错误的问题。
我只需将另一个带有单独导航容器的单独导航堆栈添加到后备选项即可解决此问题。