How to make this code cleaner? react native - react-native

I am building a stack navigator and want to make it cleaner I Tried many times but I couldn't
here is my code,
export default function Navigation() {
const {isSignedIn} = useSelector(state => state.authReducer);
return (
<Stack.Navigator
screenOptions={{
headerShown: false,
}}>
{isSignedIn ? (
<>
<Stack.Screen name="HomeDrawer" component={HomeDrawer} />
<Stack.Screen name="HomeScreen" component={HomeScreen} />
<Stack.Screen name="ProductOverview" component={ProductOverview} />
<Stack.Screen name="CartScreen" component={CartScreen} />
<Stack.Screen name="OrderOverview" component={OrderOverview} />
</>
) : (
<>
<Stack.Screen name="Login" component={Login} />
<Stack.Screen name="SignUp" component={SignUp} />
<Stack.Screen name="HomeDrawer" component={HomeDrawer} />
<Stack.Screen name="HomeScreen" component={HomeScreen} />
<Stack.Screen name="ProductOverview" component={ProductOverview} />
<Stack.Screen name="CartScreen" component={CartScreen} />
<Stack.Screen name="OrderOverview" component={OrderOverview} />
</>
)}
</Stack.Navigator>
);
}
I don't want to duplicate code like this, Is there is a way to not duplicate code?

export default function Navigation() {
const {isSignedIn} = useSelector(state => state.authReducer);
return (
<Stack.Navigator
screenOptions={{
headerShown: false,
}}>
{!isSignedIn && (
<>
<Stack.Screen name="Login" component={Login} />
<Stack.Screen name="SignUp" component={SignUp} />
</>
)}
<Stack.Screen name="HomeDrawer" component={HomeDrawer} />
<Stack.Screen name="HomeScreen" component={HomeScreen} />
<Stack.Screen name="ProductOverview" component={ProductOverview} />
<Stack.Screen name="CartScreen" component={CartScreen} />
<Stack.Screen name="OrderOverview" component={OrderOverview} />
</Stack.Navigator>
);
}
Hey, try this. I haven't tried executing this, since I don't have the environment setup now. But it should work. Hope it helps. Cheers.

Related

How do I go from the screen in the navigator to the screen in the other navigator?

function Logins() {
return (
<Provider theme={theme}>
<Stack.Navigator
initialRouteName="StartScreen"
screenOptions={{
headerShown: false,
}}
>
<Stack.Screen name="StartScreen" component={StartScreen} />
<Stack.Screen name="LoginScreen" component={LoginScreen} />
<Stack.Screen name="RegisterScreen" component={RegisterScreen} />
<Stack.Screen name="Dashboard" component={Dashboard} />
<Stack.Screen
name="ResetPasswordScreen"
component={ResetPasswordScreen}
/>
</Stack.Navigator>
</Provider>
)
}
function Drawers() {
return (
<Drawer.Navigator>
<Drawer.Screen name="Profile" component={UnderConstruction} />
<Drawer.Screen name="Popular" component={UnderConstruction} />
<Drawer.Screen name="Saved" component={UnderConstruction} />
<Drawer.Screen name="Discover" component={UnderConstruction} />
<Drawer.Screen name="Configuration" component={UnderConstruction} />
<Drawer.Screen name="Help Center" component={UnderConstruction} />
</Drawer.Navigator>
)
}
function Main() {
return (
<Stack.Navigator initialRouteName="Home">
<Stack.Screen name="Home" component={Home} />
<Stack.Screen name="Search" component={Search} />
<Stack.Screen name="Notification" component={Notification} />
<Stack.Screen name="Message" component={Message} />
</Stack.Navigator>
)
}
function Detail() {
return (
<Stack.Navigator>
<Stack.Screen name="Tweet" component={UnderConstruction} />
<Stack.Screen name="New Tweet" component={TweetButton} />
<Stack.Screen name="New Message" component={UnderConstruction} />
<Stack.Screen name="DynamicTitle" component={UnderConstruction} />
</Stack.Navigator>
)
}
export default function App() {
return (
<NavigationContainer>
<Stack.Navigator
initialRouteName="Logins"
screenOptions={{
headerMode: 'none',
}}
>
<Stack.Screen name="Logins" component={Logins} />
<Stack.Screen name="Main" component={Main} />
<Stack.Screen name="Drawer" component={Drawers} />
<Stack.Screen name="Details" component={Detail} />
</Stack.Navigator>
</NavigationContainer>
)
}
As you can see, I made a stack navigator that contains all the stack navigators, logins, main, drawers, and details.
And I want to make it possible to move between Home and New Tweet, which belong to different navigators.
I tried this.props.navigation.navigate ("New Tweet")
and this.props.navigation.navigate ("Details", {screen: "New tweet"}) inside the components on the Home screen.
But both didn't work and I got an error "NAVIGATE" with payload {"name": "New tweet"} was not handled by any navigator.
I think it's because they're different navigators. But I don't know how to do..
Change Detail to Details and New tweet to New Tweet. Try following
this.props.navigation.navigate ("Details", {screen: "New Tweet"})
I think there is no way directly to switch to a different stack navigator if they are not related to each other. From here I think this can be one option
Make the screen available in the stack that you want to switch from the home screen. For example, in the main function, if you want to switch to "detail" screen
function Main()
{
return (
<Stack.Navigator initialRouteName="Home">
<Stack.Screen name="Home" component={Home} />
<Stack.Screen name="Search" component={Search} />
<Stack.Screen name="Notification" component={Notification} />
<Stack.Screen name="Message" component={Message} />
<Stack.Screen name="Details" component={Detail} />
</Stack.Navigator>)
}
now from here your homescreen you can call this.props.navigation.navigate ("Details", {screen: "New Tweet"})
You can also look into the below thread to achieve this otherway around
React Navigation 5: Switching between different stack navigators in React native

How to wrap multiple stack screens with context provider in react navigation 5?

I would like to achieve something like the following but it is not possible because stack navigator accepts only Stack.Screens as children.
<Stack.Navigator>
<Provider1>
<Stack.Screen name="screen1" component={Screen1} />
<Stack.Screen name="screen2" component={Screen2} />
</Provider1>
<Provider2>
<Stack.Screen name="screen3" component={Screen3} />
<Stack.Screen name="screen4" component={Screen4} />
</Provider2>
</Stack.Navigator/>
I know that I could achieve this by wrapping the screens with stack navigator like so:
const stackNav1 = <Provider1>
<Stack.Navigator>
<Stack.Screen name="screen1" component={Screen1} />
<Stack.Screen name="screen2" component={Screen2} />
</Stack.Navigator>
</Provider1>
const stackNav2 = <Provider2>
<Stack.Navigator>
<Stack.Screen name="screen3" component={Screen3} />
<Stack.Screen name="screen4" component={Screen4} />
</Stack.Navigator>
</Provider2>
...
<Stack.Navigator>
<Stack.Screen name="stack1" component={stackNav1} />
<Stack.Screen name="stack2" component={stackNav2} />
</Stack.Navigator/>
Is there any simpler approaches in which I wouldn't have to define new navigators?
Try this, I might be wrong
<Stack.Navigator>
<Provider1>
<Stack.Group>
<Stack.Screen name="screen1" component={Screen1} />
<Stack.Screen name="screen2" component={Screen2} />
</Stack.Group>
</Provider1>
<Provider2>
<Stack.Group>
<Stack.Screen name="screen3" component={Screen3} />
<Stack.Screen name="screen4" component={Screen4} />
</Stack.Group>
</Provider2>
</Stack.Navigator/>

react native navigation problem ( nesting stack, drawer and bottom tab)

I'm using RN navigation v5 for my app and I'm gonna build my navigation like image below:
as you can see this app has an intro then some authentication screens and after sign in user view the home screen. so what I want is stack for intro, drawer and bottom tab navigation for my home screen. you can see my code below:
const IntroStack = createStackNavigator();
const IntroNavigation = () => {
return (
<NavigationContainer>
<IntroStack.Navigator>
<IntroStack.Screen name='intro' component={Intro} options={{ headerShown: false }} />
<IntroStack.Screen name='login' component={Login} options={{ headerShown: false }} />
<IntroStack.Screen name='createAccount' component={CreateAccount} options={{ headerShown: false }} />
<IntroStack.Screen name='forgotPassword' component={ForgotPassword} options={{ headerShown: false }} />
<IntroStack.Screen name='enterCode' component={EnterCode} options={{ headerShown: false }} />
<IntroStack.Screen name='changePassword' component={ChangePassword} options={{ headerShown: false }} />
<IntroStack.Screen name='home' component={Home} options={{ headerShown: false }} />
</IntroStack.Navigator>
</NavigationContainer>
)
}
const Drawer = createDrawerNavigator();
const Tab = createBottomTabNavigator();
const TabNavigation = () => {
return (
<Tab.Navigator>
<Tab.Screen name="home" component={Home} />
<Tab.Screen name="worldTour" component={WorldTour} />
<Tab.Screen name="Outlet" component={Outlet} />
<Tab.Screen name="Profile" component={Profile} />
<Tab.Screen name="OutTherapists" component={OurTherapists} />
</Tab.Navigator>
);
}
const DrawerNavigation = () => {
const dimentions = useWindowDimensions();
return (
<Drawer.Navigator drawerStyle={{ width: dimentions.width }} drawerContent={props => <DrawerContent />}>
<Drawer.Screen name="home" component={IntroNavigation} />
</Drawer.Navigator>
);
}
export default TabNavigation;
but this did not work. I tried to read docs and watch some tutorials but I couldn't find something similar. I know somehow I must nest this stacks to each other but none of my tried ways achieve what I want. any help would be appreciated.
const IntroNavigation = () => {
return (
<NavigationContainer>
<IntroStack.Navigator>
<IntroStack.Screen name='intro' component={Intro} options={{ headerShown: false }} />
<IntroStack.Screen name='login' component={Login} options={{ headerShown: false }} />
<IntroStack.Screen name='createAccount' component={CreateAccount} options={{ headerShown: false }} />
<IntroStack.Screen name='forgotPassword' component={ForgotPassword} options={{ headerShown: false }} />
<IntroStack.Screen name='enterCode' component={EnterCode} options={{ headerShown: false }} />
<IntroStack.Screen name='changePassword' component={ChangePassword} options={{ headerShown: false }} />
<IntroStack.Screen name='home' component={DrawerNavigation} options={{ headerShown: false }} />
</IntroStack.Navigator>
</NavigationContainer>
)
}
const Drawer = createDrawerNavigator();
const DrawerNavigation = () => {
const dimentions = useWindowDimensions();
return (
<Drawer.Navigator drawerStyle={{ width: dimentions.width }} drawerContent={props => <DrawerContent />}>
<Drawer.Screen name="Home" component={TabNavigation} />
</Drawer.Navigator>
);
}
const Tab = createBottomTabNavigator();
const TabNavigation = () => {
return (
<Tab.Navigator>
<Tab.Screen name="Home" component={Home} />
<Tab.Screen name="WorldTour" component={WorldTour} />
<Tab.Screen name="Outlet" component={Outlet} />
<Tab.Screen name="Profile" component={Profile} />
</Tab.Navigator>
);
}
export default IntroNavigation;
Your structure should be like that for Tabs:
<Tab.Navigator>
<Tab.Screen name="home" component={DrawerStack} />
<Tab.Screen name="worldTour" component={WorldTour} />
<Tab.Screen name="Outlet" component={Outlet} />
<Tab.Screen name="Profile" component={Profile} />
<Tab.Screen name="OutTherapists" component={OurTherapists} />
</Tab.Navigator>
You should use this tab navigator as screen in main stack navigator like this:
<NavigationContainer>
<IntroStack.Navigator>
<IntroStack.Screen name='intro' component={Intro} options={{ headerShown: false }} />
<IntroStack.Screen name='login' component={Login} options={{ headerShown: false }} />
<IntroStack.Screen name='createAccount' component={CreateAccount} options={{ headerShown: false }} />
<IntroStack.Screen name='forgotPassword' component={ForgotPassword} options={{ headerShown: false }} />
<IntroStack.Screen name='enterCode' component={EnterCode} options={{ headerShown: false }} />
<IntroStack.Screen name='changePassword' component={ChangePassword} options={{ headerShown: false }} />
<IntroStack.Screen name='Tabs' component={Tabs} options={{ headerShown: false }} />
</IntroStack.Navigator>
</NavigationContainer>
In addition, the name of the screen should not be same as you have 'home' screen in each navigator, this will cause conflict when navigating from navigation ref.
For signup flow, you can follow this procedure:
https://reactnavigation.org/docs/upgrading-from-4.x/#switch-navigator

React Native Stack Navigation Screen Doesn't Exist

In App.js I have the following Stack Navigator:
<NavigationContainer>
<Stack.Navigator>
{user ? (
<Stack.Screen name="Home">
{(props) => <HomeScreen {...props} extraData={user} />}
</Stack.Screen>
) : (
<>
<Stack.Screen name="Login" component={LoginScreen} />
<Stack.Screen name="Registration" component={RegistrationScreen} />
<Stack.Screen name="Profile" component={ProfileScreen} />
</>
)}
</Stack.Navigator>
</NavigationContainer>
In the HomeScreen, I am trying to navigate to the "Profile" screen:
export default function HomeScreen(props) {
const onProfilePress = () => {
props.navigation.navigate('Profile')
};
return (
<View style={styles.container}>
<TouchableOpacity style={styles.button} onPress={onProfilePress}>
<Text style={styles.buttonText}>Profile</Text>
</TouchableOpacity>
</View>
);
}
However, I get a
The action 'NAVIGATE' with payload {"name":"Profile"} was not handled by any navigator.
Does anyone know how to fix?
Profile is only part of the stack when user is true.
Perhaps you meant to do something like this:
<NavigationContainer>
<Stack.Navigator>
{user ? (
<>
<Stack.Screen name="Home">
{(props) => <HomeScreen {...props} extraData={user} />}
</Stack.Screen>
<Stack.Screen name="Profile" component={ProfileScreen} />
</>
) : (
<>
<Stack.Screen name="Login" component={LoginScreen} />
<Stack.Screen name="Registration" component={RegistrationScreen} />
</>
)}
</Stack.Navigator>
</NavigationContainer>

ReactNative- Tab Navigator Inside Stack Navigator

Need to Show Tabs For Home Module after Signup Module
using React-navigation
Working Code with Only Stack Screens
const Stack = createStackNavigator();
const Bottom = createBottomTabNavigator();
render() {
return (
<NavigationContainer>
<Stack.Navigator initialRouteName="Welcome" headerMode='none' >
<Stack.Screen name="Welcome" component={WelcomeScreen}
options={{
title: '',
headerBackTitleVisible: false,
headerBackTitle: '',
headerShown: true
}}
/>
<Stack.Screen name="Login" component={LoginScreen} />
<Stack.Screen name="Signup" component={SignupScreen} />
<Stack.Screen name="ResetPassword" component={ResetPasswordScreen} />
</Stack.Navigator>
</NavigationContainer>
);
}
Need to show Tab from SigninScreen Button
Tab 1: Dashboard:
Tab 2: Profile
Tried Code:
<Bottom.Navigator initialRouteName="Dashboard" >
<Bottom.Screen name="Dashboard" component={TabDashboard} />
<Bottom.Screen name="Profile" component={TabProfile} />
</Bottom.Navigator>
Now I need to combine these two block of codes so I can navigate to Tabs
Tab screen will have further navigations
The idea would be to wrap the tabs screen inside component and add it to the stack conditionally.
const HomeScreen = () =>{
return (
<Bottom.Navigator initialRouteName="Dashboard" >
<Bottom.Screen name="Dashboard" component={TabDashboard} />
<Bottom.Screen name="Profile" component={TabProfile} />
</Bottom.Navigator>
);
}
Your stack should change as below
render() {
return (
<NavigationContainer>
<Stack.Navigator initialRouteName="Welcome" headerMode='none' >
{
this.state.isSignedIn ? (
<>
<Stack.Screen name="Welcome" component={WelcomeScreen} />
<Stack.Screen name="Login" component={LoginScreen} />
<Stack.Screen name="Signup" component={SignupScreen} />
<Stack.Screen name="ResetPassword" component={ResetPasswordScreen} />
</>
) : (
<>
<Stack.Screen name="ResetPassword" component={HomeScreen} />
</>
)
}
</Stack.Navigator>
</NavigationContainer>
);
}
IsSignedIn can be the state variable or a variable that you store the logged in status
You can refer the authentication flows
https://reactnavigation.org/docs/auth-flow