21

Following is the hierarchy of my app navigators

├── appNavigator ( Bottom Tab Navigator)

  • ├── feed (Stack Navigator)

    • postDetailScreen
    • pageDetailScreen
    • ProfileDetailScreen
    • ...other screens
  • ├── notifications (Stack Navigator)

    • ProfileDetailScreen
    • PageDetailScreen
    • PostDetailScreen
    • ...other screens
  • ├── profile (Stack Navigator)

    • ProfileDetailScreen
    • PageDetailScreen
    • PostDetailScreen
    • ...other screens

Now the problem is I have to duplicate the screens (ProfileDetail, PostDetail and PageDetail) which are common among all the stacks in order for them to be accessible within the stacks.

Is there a better solution for this usecase. Where should I put the common screens so that they are available in all the children stack and I don't have to duplicate them everywhere.

Here's an open github issue which I went through but could not find a good solution Isuue

Ayesha Iftikhar
  • 1,028
  • 2
  • 11
  • 27
  • Can you please tell that which props or data are separating these components from one another. Then I can suggest you a solution with that. – Shahnawaz Hossan Jun 24 '20 at 08:58

3 Answers3

0

Since you have multiple screens in common and some different data (title, description, etc), you can create only one common stack navigator with multiple screens, and then you can call it from anywhere else.

Your stack navigator can be like this:

export default class StackNavigator extends React.Component {

    render() {

        const { stackName1, stackComponent1, stackName2, stackComponent2, stackName3, stackComponent3 } = this.props;

        // console.log("props");
        // console.log(stackName1);
        // console.log(stackComponent1);

        return (
            <Stack.Navigator initialRouteName={stackName1}>
                <Stack.Screen
                    name={stackName1}
                    component={stackComponent1}
                    initialParams={{key: "value"}}
                />
                <Stack.Screen
                    name={stackName2}
                    component={stackComponent2}
                    initialParams={{key: "value"}}
                />
                <Stack.Screen
                    name={stackName3}
                    component={stackComponent3}
                    initialParams={{key: "value"}}
                />
            </Stack.Navigator>
        )
    }
}

Then call the navigator like this from any screen(feed, notifications, profile):

<StackNavigator stackName1="PostDetailScreen" stackComponent1={PostDetailScreen} stackName2="PageDetailScreen" stackComponent2={PageDetailScreen} stackName3="ProfileDetailScreen" stackComponent3={ProfileDetailScreen}/>

Also if you want to send extra params to every single page from stack navigator, you can send those via initialParams={{key: "value"}} which I have added into every single screen of stack navigator. If you want to receive this props from the specific screen just access the key by this.props.route.params.key which is described here.

If you have more screens on the stack, then you can pass components' info in an array.

Shahnawaz Hossan
  • 2,695
  • 2
  • 13
  • 24
0

Duplication is indeed a bad practice we must avoid here. I don't know if you ever think of creating an entire stack that only 'common' screens locate or just surrounding stack and screens into another parent stack. It's like a folder structure, refer code below:

Something like:

<Stack.Navigator>
  <Stack.Screen name={'FeedStack'} component={FeedStack} />
  <Stack.Screen>...NotificationStack (same above)
  <Stack.Screen>...ProfileStack (same above)
  <Stack.Screen>...CommonStack (same above)
  ...or here
</Stack.Navigator>

// inside every child stack, define a Stack and pass all relevant screens to the stack, for example the FeedStack: 

    <Stack.Navigator>    
       <Stack.Screen name={'Feed1Screen'} component={Feed1Screen} />
       <Stack.Screen name={'Feed2Screen'} component={Feed2Screen} />
    </Stack.Navigator>

then to navigate from one Stack to the other, let's say you're under FeedStack, in Feed1Screen presumably, and want to be in Notification1Screen which lies under NotificationStack, use:

navigationRef.navigate('NotificationStack', {
        screen: 'Notification1Screen', // whatever screenName under NotificationStack goes here
        params: {
           // ...whatever parameter passed to "Notification1Screen" goes here.
        }
});

Hope that might help :>

ndnam198
  • 21
  • 5
0

Start by creating a directory within your project structure to store the shared screens. For example, you might create a directory named screens at the root of your project.

Within the screens directory, create subdirectories based on the logical sections of your application. For instance:

screens/
├── Auth/
│   ├── LoginScreen.js
│   ├── SignupScreen.js
│   └── ...
├── Dashboard/
│   ├── HomeScreen.js
│   ├── ProfileScreen.js
│   └── ...
└── ...

Define Common Components ------>>> 
If your shared screens have components that are used across multiple screens, consider creating a components directory within each screen's directory or in the main components directory. This helps keep the components closely related to the screens they're used in.

Import and Use Shared Screens ------->>
In your different stack navigators, you can then import the shared screens from the organized directory structure and use them as needed

import { LoginScreen, SignupScreen } from '../screens/Auth';

const AuthStack = createStackNavigator();

function AuthNavigator() {
  return (
    <AuthStack.Navigator>
      <AuthStack.Screen name="Login" component={LoginScreen} />
      <AuthStack.Screen name="Signup" component={SignupScreen} />
    </AuthStack.Navigator>
  );
}

Navigation Hierarchies ---->>
Depending on your app's structure, you might have different navigators, such as AppNavigator, AuthNavigator, MainNavigator, etc. Each of these navigators can import and include the appropriate shared screens.
ND verma
  • 171
  • 1
  • 9