我一直在 React-Native 上开发一个应用程序。我面临的问题是,我已经在我的 React-Native 应用程序中实现了 gorhoms 底部工作表,当我单击当前位置时,它应该可以工作。这个底部工作表在 Android 上工作,就像它打开一样,但它在 iOS 上不起作用,因为导航路由器有问题。当我永久删除仅在我的 iPhone 上呈现的初始屏幕时。我不知道问题是什么。
我在这里分享了我在应用程序内渲染的底部表单组件的代码。然后是顶部导航组件,我在当前位置添加了
onClick
,当在底部表单存储中设置状态时,其状态会在组件的映射上发生变化,并且聚焦的底部表单将打开,无论其是否为位置、住房或工作。此顶部导航在选项卡导航器屏幕中的各个组件内呈现,并且导航路由器控制屏幕之间的切换。因此,正如您在导航路由器中看到的,堆栈中提到的处于 isEstablished
状态的屏幕,当我注释掉这些屏幕且其余逻辑相同时,底部工作表将在 iOS 内打开。否则就不会了。
"react": "18.2.0",
"react-native": "0.72.6",
"react-native-gesture-handler": "~2.12.0",
"@react-navigation/native-stack": "^6.9.17",
"@react-navigation/stack": "^6.3.20",
"expo": "~49.0.15",
"react-native-reanimated": "^3.3.0",
"@gorhom/bottom-sheet": "^4.6.0",
import React, { useCallback, useMemo, useRef } from "react";
import BottomSheet, { BottomSheetView} from "@gorhom/bottom-sheet";
import { GestureHandlerRootView } from "react-native-gesture-handler";
import { SafeAreaView, StyleSheet, Text, View } from "react-native";
import LocationBottomSheetContent from "../Location/LocationBottomSheetContent";
import HousingFilterBottomSheet from "../Filters/HousingFilterBottomSheet";
import useBottomSheetStore from "../../../Stores/BottomSheetStore";
import JobsFiltersBottomSheet from "../Filters/JobsFiltersBottomSheet";
import { useReducedMotion } from "react-native-reanimated";
const mapping =
{
"Location": LocationBottomSheetContent,
"HousingFilters": HousingFilterBottomSheet,
"JobsFilters": JobsFiltersBottomSheet,
// undefined,
};
const BottomSheetComponent = () => {
const bottomSheetRef = useRef<BottomSheet>(null);
const snapPoints = useMemo(() => ["100%"], []);
const handleSheetChanges = useCallback((index: number) => {
console.log("handleSheetChanges", index);`your text`
}, []);
const { visibleBottomSheet } = useBottomSheetStore();
const Comp = visibleBottomSheet ? mapping[visibleBottomSheet] : null;
if (!visibleBottomSheet) return <React.Fragment key={123}></React.Fragment> ;
// console.log(visibleBottomSheet,Comp);
return(
<GestureHandlerRootView key={456} style= {styles.bottomsheet} >
<View style={styles.container}>
<BottomSheet
ref={bottomSheetRef}
index={ 0 }
snapPoints={snapPoints}
onChange={handleSheetChanges}
backgroundStyle={styles.backgroundStyle}
enablePanDownToClose={true}
// containerHeight={100}
// enableDynamicSizing={true}
>
<BottomSheetView style={styles.contentContainer}>
<LocationBottomSheetContent />
</BottomSheetView>
</BottomSheet>
</View>
</GestureHandlerRootView>
// <View style={{flex:1,zIndex: 999,}}>
// <Text> {visibleBottomSheet? "true" : "False"}</Text>
// </View>
);
};
const styles = StyleSheet.create({
bottomsheet: {
flex: 1,
zIndex: 999,
// backgroundColor: "gray"
height: "100%",
// display: "flex",
},
contentContainer: {
// flex: 1,
// alignItems: "center",
},
container:{
flex: 1,
padding: 24,
},
backgroundStyle: {
borderTopLeftRadius: 40,
borderTopRightRadius: 40,
// backgroundColor: "gray",
},
// bottomSheetContainer: {r
// // height: 300
// }
});
export default BottomSheetComponent;
import { StatusBar } from "expo-status-bar";
import React from "react";
import Splash from "./src/components/Screens/OnboardingScreens/Splash";
import NavigationRouter from "./src/components/routes/NavigationRouter";
import BottomSheetComponent from "./src/components/Screens/BottomSheets/BottomSheet/BottomSheetComponent";
const App = () => {
return (
<Splash>
<StatusBar style="auto" />
<NavigationRouter />
<BottomSheetComponent />
</Splash>
);
};
export default App;
import React from "react";
import { View,Text, StyleSheet,TouchableOpacity, SafeAreaView } from "react-native";
import HamburgerMenu from "../svgs/HamburgerMenu";
import LocationSvg from "../svgs/LocationSvg";
import { useNavigation } from "@react-navigation/native";
import BlueLocationIcon from "../svgs/BlueLocationIcon";
import useBottomSheetStore from "./Stores/BottomSheetStore";
const TopNavigation: React.FC = ()=> {
const navigation = useNavigation();
const locationClick = () => {
navigation.navigate("MapsScreen");
};
const { setVisibleBottomSheet } = useBottomSheetStore();
const toggleBottomSheet = () => {
setVisibleBottomSheet("Location");
console.log("location bts toggled");
};
return(
<SafeAreaView style={styles.container}>
<View style={styles.Icon}>
<HamburgerMenu />
</View>
<TouchableOpacity style={styles.topNavText} onPress={toggleBottomSheet}>
<Text style={[styles.heading]}>Current Location</Text>
<View style={styles.location}>
<BlueLocationIcon/>
<Text style={[styles.subHeading, styles.mainText, styles.locationText]}>Iceland</Text>
</View>
</TouchableOpacity>
<TouchableOpacity
style= {[styles.Icon]}
onPress = {locationClick}
>
<LocationSvg />
</TouchableOpacity>
</SafeAreaView>
);
};
const styles = StyleSheet.create({
container: {
flexDirection: "row",
justifyContent: "space-between",
padding:10,
},
Icon: {
borderColor: "#EDEDED",
borderStyle: "solid",
borderRadius: 10,
borderWidth: 1,
padding: 8,
},
heading: {
fontFamily: "Poppins_Paragraph",
fontSize: 12,
},
subHeading: {
fontFamily: "Poppins_Heading",
fontSize: 14,
},
mainText: {
textAlign: "center"
},
location: {
flexDirection: "row",
alignItems: "center"
},
locationText: {
marginLeft: 7,
},
topNavText: {
justifyContent: "center",
alignContent: "center",
},
});
export default TopNavigation;
import {create} from "zustand";
type BottomSheetType = "Location" | "HousingFilters" | "JobsFilters" |undefined;
type BottomSheetState = {
visibleBottomSheet : BottomSheetType;
setVisibleBottomSheet: (visibleBottomSheet: BottomSheetType) => void;
}
const useBottomSheetStore = create<BottomSheetState>((set) => ({
visibleBottomSheet : undefined,
setVisibleBottomSheet: (visibleBottomSheet) => {
// console.log("Before update:", visibleBottomSheet);
set((state) => ({
...state,
visibleBottomSheet: visibleBottomSheet
}));
// console.log("After update:", visibleBottomSheet);
}
}));
export default useBottomSheetStore;
import HousingScreen from "./Screens/HousingScreen/HousingScreen";
import React, { useEffect } from "react";
import { createBottomTabNavigator } from "@react-navigation/bottom-tabs";
import { Dimensions, StyleSheet, View } from "react-native";
import { RouteProp } from "@react-navigation/native";
import { StackNavigationProp } from "@react-navigation/stack";
import { RootStackParamList } from "./routes/NavigationRouter";
import JobsScreen from "./Screens/JobsScreen/JobsScreen";
import SearchScreen from "./Screens/SearchScreen/SearchScreen";
import SearchSvg from "../svgs/SearchSvg";
import JobSvg from "../svgs/JobSvg";
import HousingSvg from "../svgs/HousingSvg";
import HeartSvg from "../svgs/HeartSvg";
import ProfileSvg from "../svgs/ProfileSvg";
import FocusedSearchSvg from "../svgs/FocusedSearchSvg";
import FocusedJobsSvg from "../svgs/FocusedJobsSvg";
import FocusedHousingSvg from "../svgs/FocusedHousingSvg";
import FocusedHeartSvg from "../svgs/FocusedHeartSvg";
import BottomSheetComponent from "./Screens/BottomSheets/BottomSheet/BottomSheetComponent";
import useStore from "./Stores/store";
// import useStore from "../Stores/store";
type TabNavigatorScreenRouteProp = RouteProp<RootStackParamList, keyof RootStackParamList>;
type TabNavigatorScreenNavigationProp = StackNavigationProp<RootStackParamList>;
type TabNavigatorProps = {
route?: TabNavigatorScreenRouteProp;
navigation: TabNavigatorScreenNavigationProp;
};
const Tab = createBottomTabNavigator();
const TabNavigator: React.FC<TabNavigatorProps> = () => {
const isEstablishedUser = useStore((state) => state.isEstablishedUser);
const showTabNavigator = useStore((state) => state.showTabNavigator);
// const hideTabNavigator = useStore((state) => state. hideTabNavigator);
useEffect(() => {
if (!isEstablishedUser) {
showTabNavigator();
console.log("user extablished");
}
}, []);
return (
<View style={styles.viewStyle}>
<Tab.Navigator
screenOptions={{
tabBarStyle: {
backgroundColor: "black",
borderRadius: 30,
width: 340,
height: 56,
position:"absolute",
marginBottom: 10,
left: (Dimensions.get("window").width / 2) - 170,
},
tabBarShowLabel: false,
tabBarActiveTintColor: "white",
tabBarInactiveTintColor: "gray",
headerShown: false,
}}
>
<Tab.Screen
name="SearchScreen"
component={SearchScreen}
options={{
tabBarIcon: ({ focused }) => (
<View>
{focused && <FocusedSearchSvg/>}
{!focused && <SearchSvg />}
</View>
),
}}
/>
<Tab.Screen
name="Jobs"
component={JobsScreen}
options={{
tabBarIcon: ({ focused }) => (
<View>
{focused && <FocusedJobsSvg/>}
{!focused && <JobSvg />}
</View>
),
}}
/>
<Tab.Screen
name="Home"
component={HousingScreen}
options={{
tabBarIcon: ({focused}) => (
<View>
{focused && <FocusedHousingSvg/>}
{!focused && <HousingSvg />}
</View>
),
}}
/>
<Tab.Screen
name="Favorites"
component={HousingScreen}
options={{
tabBarIcon: ({focused}) => (
<View>
{focused && <FocusedHeartSvg/>}
{!focused && <HeartSvg />}
</View>
),
}}
/>
<Tab.Screen
name="Person"
component={HousingScreen}
options={{
tabBarIcon: () => (
<ProfileSvg />
),
}}
/>
</Tab.Navigator>
{/* <BottomSheetComponent /> */}
</View>
);
};
const styles = StyleSheet.create({
viewStyle: {
flex: 1,
width: "100%",
}
});
export default TabNavigator;
import React from "react";
import TabNavigator from "../TabNavigator";
import OnboardingOne from "../Screens/OnboardingScreens/OnboardingOne";
import OnboardingTwo from "../Screens/OnboardingScreens/OnboardingTwo";
import OnboardingThree from "../Screens/OnboardingScreens/OnboardingThree";
import OnboardingFour from "../Screens/OnboardingScreens/OnboardingFour";
import Register from "../Screens/OnboardingScreens/Register";
import Selection from "../Screens/WelcomeScreen";
import TopNavigation from "../TopNavigation";
import { NavigationContainer } from "@react-navigation/native";
import { createNativeStackNavigator } from "@react-navigation/native-stack";
import useStore from "../Stores/store";
import MapsScreen from "../Screens/MapsScreens/MapsScreen";
import BottomSheetComponent from "../Screens/BottomSheets/BottomSheet/BottomSheetComponent";
export type RootStackParamList = {
SearchScreen: undefined;
JobsScreen: undefined;
HousingScreen: undefined;
Favorites: undefined;
Person: undefined;
Selection: undefined;
TabNavigator: undefined;
TopNavigation: undefined;
MapsScreen: undefined;
};
const NavigationRouter: React.FC = () =>{
const Stack = createNativeStackNavigator();
const isEstablishedUser = useStore((state) => state.isEstablishedUser);
return (
<NavigationContainer>
<Stack.Navigator screenOptions={{ headerShown: false, animation: "slide_from_right" }}>
{!isEstablishedUser && (
<>
<Stack.Screen name="OnboardingOne" component={OnboardingOne} />
<Stack.Screen name="OnboardingTwo" component={OnboardingTwo} />
<Stack.Screen name="OnboardingThree" component={OnboardingThree} />
<Stack.Screen name="OnboardingFour" component={OnboardingFour} />
<Stack.Screen name="Register" component={Register} />
</>
)}
<Stack.Screen
name="TabNavigator"
component={TabNavigator as React.ComponentType }
options={{ presentation: "transparentModal" }}
/>
<Stack.Screen name="Selection" component={Selection} />
<Stack.Screen name="TopNavigation" component={TopNavigation} />
<Stack.Screen name="MapsScreen" component={MapsScreen} />
{/* <Stack.Screen name="BottomSheet" component={BottomSheetComponent} /> */}
{/* <BottomSheetComponent /> */}
</Stack.Navigator>
</NavigationContainer>
);
};
export default NavigationRouter;
到目前为止我已经尝试做了很多事情。一开始,我一直关注所涉及的组件和商店,即
<BottomSheetComponent/>
、<App>
、<BottomSheetStore/>
和 <TopNavigation/>
。我尝试从 <BottomSheetComponent/>
中删除 if/else 逻辑,但后来我发现问题在于导航路由器是如何实现的以及选项卡导航器是如何实现的。因为当在选项卡导航器屏幕内时,当我直接在应用程序内渲染它时,底部表不起作用,它开始工作,但显然我不希望这样。我也尝试在 Github 上搜索相同的问题,但人们写道我的 React-native-reanimated 版本可能存在问题,但我认为这不是这里的问题。
为了更安全,请定制您自己的。我现在面临类似的问题。我将从头开始构建一些我将来可以控制的东西,我可能会与你分享