前面我们已经准备好了expo router
,现在我们来写页面
首先我们先定义一个auth
用于全局的用户操作,新建context/auth.tsx
tsx
import { createContext, useContext, useState } from "react";
const AuthContext = createContext({
user: null,
signIn: (val: any) => {},
signOut: () => {},
});
export const useAuth = () => useContext(AuthContext);
export function AuthProvider({
children,
userCredentials,
}: {
children: any;
userCredentials: any;
}) {
const [user, setAuth] = useState(userCredentials);
return (
<AuthContext.Provider
value={{
signIn: (userCredentials) => setAuth(userCredentials),
signOut: () => setAuth(null),
user,
}}>
{children}
</AuthContext.Provider>
);
}
主要抛出一个useAuth
一个AuthProvider
来包裹layout,达到复用context的作用
页面
我们现在来编写页面结构,结构如下:
新建app/_layout.tsx
tsx
import { Stack } from "expo-router";
import { useState } from "react";
import { AuthProvider } from "../context/auth";
export default function Layout() {
const [loadedUser, setLoadedUser] = useState(null);
return (
<AuthProvider userCredentials={loadedUser}>
<Stack>
<Stack.Screen
name="(main)/(tabs)"
options={{
headerShown: false,
}}></Stack.Screen>
</Stack>
</AuthProvider>
);
}
用于在首次进入页面的时候,进入指向(main)/(tabs)
下面的页面
新建关于页app/about.tsx
tsx
import { useLocalSearchParams, useRouter } from "expo-router";
import { View, Text } from "react-native";
export default function Details() {
const router = useRouter();
const params = useLocalSearchParams();
return (
<View style={{ flex: 1, alignItems: "center", justifyContent: "center" }}>
<Text
onPress={() => {
router.setParams({ name: "Updated" });
}}>
Update the title
</Text>
</View>
);
}
这种路由地址和文件系统路径有关,至于(auth)``(main)
这种其实是一样的目录,只是为了方便组织文件,做的路由分组
新建登录页app/(auth)/login.tsx
tsx
import { useLocalSearchParams, useRouter } from "expo-router";
import { useState } from "react";
import { Pressable, Text, View } from "react-native";
import { useAuth } from "../../context/auth";
export default function Login() {
const router = useRouter();
const params = useLocalSearchParams();
const [email, setEmail] = useState("1@qq.com");
const { signIn } = useAuth();
const onLogin = async () => {
signIn({ email });
router.back();
};
return (
<View>
<Pressable onPress={onLogin}>
<Text>Login</Text>
</Pressable>
</View>
);
}
tabs
导航栏页面,我们先新建app/(main)/(tabs)/cart.tsx
, app/(main)/(tabs)/category.tsx
,app/(main)/(tabs)/profile.tsx
,app/(main)/(tabs)/index.tsx
并且都填入类似的初始化代码:
tsx
import { View, Text } from "react-native";
export default function Profile() {
return (
<View>
<Text>Profile screen</Text>
</View>
);
}
因为我们目前只是组织项目结构,所以不急于写代码
然后我们修改app/(main)/(tabs)/_layout.tsx
tsx
import { FontAwesome } from "@expo/vector-icons";
import { Tabs } from "expo-router";
export default function Layout() {
return (
<Tabs
screenOptions={{
tabBarActiveTintColor: "#05bfdb",
}}>
<Tabs.Screen
name="index"
options={{
title: "feed",
tabBarIcon: ({ color }) => <FontAwesome name="home" size={24} color={color} />,
}}
/>
<Tabs.Screen
name="category"
options={{
tabBarIcon: ({ color }) => <FontAwesome name="search" size={24} color={color} />,
}}
/>
<Tabs.Screen
name="cart"
options={{
tabBarIcon: ({ color }) => <FontAwesome name="bell" size={24} color={color} />,
}}
/>
<Tabs.Screen
name="profile"
options={{
tabBarIcon: ({ color }) => <FontAwesome name="user" size={24} color={color} />,
}}
/>
</Tabs>
);
}
囊括每一个tab的screen,注意这里需要安装@expo/vector-icons
依赖:
shell
npx expo install @expo/vector-icons
好了 现在打开页面效果如下: