Comments (11)
Closing since React Navigation 5 implements prop-based configuration.
from rfcs.
My 2 cents, this is how I accomplished my desire for a dynamic initial route:
quincycs/react-native-q-starter@69f8b76
from rfcs.
My use case is simple, I have a tab navigator that I wan to launch to the specific screen define in the tab.
This is something possible in UITabBarController in iOS.
In my use case, the switch navigator suggestion doesn’t make sense though
from rfcs.
IMO we should be able to pass all navigator and router options as normal props. But for the router it will need a lot of refactoring since they are created at declaration time rather than during render.
from rfcs.
Copying over my comment from #458
if you need to set the initialRouteName as a prop it is because there is some data that you need to fetch asynchronously before you render the app navigation. another way to handle this is to use a switchnavigator and have a screen that you show when you are fetching the async data, then navigate to the appropriate initial route with params when necessary. see https://reactnavigation.org/docs/auth-flow.html for a full example of this.
from rfcs.
I want to add my usecase for this RFC, as providing only initialRouteName
may not be flexible enough for me.
In my app, I have a "global navigation" that is always mounted, and when the user trigger a process, there's some kind of "command wizzard" that is made using a StackNav of multiple screens, one after the other. This StackNav is not always mounted, it gets mounted only when user starts the command process. And the app need the ability to "restore" the command process, which actually means that we should mount the StackNav with a given initial state and multiple stack screens initially, potentially in different orders, and not just having the ability to set the initial root screen.
A workaround to setup an initial StackNav state on mount is the following:
class CommandScreenNavigator extends React.PureComponent {
componentDidMount() {
this.setupInitialNavState();
}
setupInitialNavState = () => {
let initialAction = undefined;
// Read from parent main app navigation
const restoreCommandProcessState = this.props.navigation.state.params.restoreCommandProcessState;
if ( restoreCommandProcessState && restoreCommandProcessState.toScreen === 3 ) {
initialAction = NavigationActions.reset({
index: 2,
actions: [
NavigationActions.navigate({routeName: FirstScreen}),
NavigationActions.navigate({routeName: SecondScreen}),
NavigationActions.navigate({routeName: ThirdScreen}),
],
});
}
else if ( restoreCommandProcessState && restoreCommandProcessState.toScreen === 2 ) {
initialAction = NavigationActions.reset({
index: 1,
actions: [
NavigationActions.navigate({routeName: FirstScreen}),
NavigationActions.navigate({routeName: SecondScreen}),
],
});
}
initialAction && this.stackNavigation.dispatch(initialAction);
};
render() {
const commandWorkflowScreenProps = {...};
return (
<CommandScreenStackNavigation
ref={c => this.stackNavigation = c}
screenProps={commandWorkflowScreenProps}
/>
);
}
}
So, instead of ability to set initialRouteName, I think it would be more powerful to give ability to initialise the state of a stateful StackNav, which would actually permit to set an initialRouteName.
Potential workarounds for setting initialRouteName / initialState for my usecase would be:
- Connecting the StackNav to my main app nav (making it stateless), and then when navigating to the command workflow screen, mount child stacknav with sub-actions
- Make the stacknav stateless and store the state one step above (in React component or in Redux), using
addNavigationHelpers
etc
from rfcs.
I think the tab navigator example is a good one: when presenting it, you may want to show a different default tab based on the screen props, for instance. Similar with a switch navigator. You could navigate from the outside to the proper screen, but I rather present the navigation with some props and let it decide its initial state.
In a stack navigator, maybe I have a three steps stack (A, B, C) where A contains a list and B is a details screen. I may want to show the navigator either starting from A, where I can fetch some items and show their details, or if I have already an item, I can skip A and show B directly.
from rfcs.
As @satya164 said, I pass router options as props to navigator, I think this has already met the demand. but I still need some official documentation or feature for this situation.
from rfcs.
Hi, @harvey-woo. Can you share a small example with us?
from rfcs.
@danielmartinprieto
I just simply create a routerConfig2Navigator
function to convert routerConfig to Navigator component
const type2NavigatorComponentCreater = {
switch: createSwitchNavigator,
bottomTab: createBottomTabNavigator
}
type Component = FunctionComponent | React.ComponentClass
type RouterConfig = {
type: keyof typeof type2NavigatorComponentCreater,
initialRouteName ?: string,
transitionConfig: () => any,
routes: {
[key: string] : RouterConfig | Component
}
} & {
[ otherConfig: string ]: any
}
function isComponent(target: any): target is Component {
return typeof target === 'function'
}
function routerConfig2Navigator(routerConfigOrComponent: RouterConfig | Component, initialRouteNames ?: string[]) {
if (isComponent(routerConfigOrComponent)) {
return routerConfigOrComponent
}
const { routes, type, ...options } = routerConfigOrComponent
let initialRouteName: string | undefined
let subInitialRouteNames: string[]
if (initialRouteNames && initialRouteNames.length) {
[ initialRouteName, ...subInitialRouteNames ] = initialRouteNames
}
const innerRoutes: { [key: string]: any } = {}
Object.keys(routes).forEach(key => {
innerRoutes[key] = routerConfig2Navigator(routes[key], subInitialRouteNames)
})
return type2NavigatorComponentCreater[type](innerRoutes, {
...options,
...(initialRouteName ? {
initialRouteName
}: {})
})
}
const routerConfig: RouterConfig = {
type: 'switch',
initialRouteName: 'Login',
routes: {
Login,
Home: {
type: 'bottomTab',
tabBarComponent: HomeFooterTab,
initialRouteName: 'HomeMy',
routes: {
HomeIndex,
HomeRecord,
HomeMy
}
}
}
}
export default class App extends Component {
render() {
const RouterContainer = createAppContainer(routerConfig2Navigator(routerConfig, ['Login']))
const content = <RouterContainer></RouterContainer>
return <RouterContainer></RouterContainer>
}
}
from rfcs.
const TabsNav = createBottomTabNavigator({
A: stackA,
B: stackB,
C: stack C
}, {
order: ['A', 'B', 'C'],
initialRouteName: 'A', //<-- want to change this acc. to “this.props.navigation.getParam('fromWhere', ‘’);”
tabBarPosition: 'bottom',
});
//say I have a component 'HomeDash'
//SCREEN
render() {
return (
<HomeDashContainer
ref={nav => (this.homeDashRef = nav)}
screenProps={{ homeDashNav: this.props.navigation }} />
);
}
const HomeDashContainer = createAppContainer(TabsNav);
export default HomeDash;
// I have required route name in an async method that I called in constructor or UNSAFE_componentWillMount
My requirement is to set initial tab on basis of “this.props.navigation.getParam('fromWhere', ‘’);”
Any running solution will be helpful…
from rfcs.
Related Issues (20)
- Action property that indicates to routes that they should not change index HOT 1
- Improve ergonomics of back HOT 1
- Navigator config to pass params down HOT 1
- Add unsetParams to navigation prop HOT 2
- Reset state action HOT 2
- Expose logic for initializing state of createAppContainer HOT 4
- On will/didFocus subscribe, stop firing the listener if current screen is focused HOT 2
- Idea: Preloading HOT 6
- <StaticNavigator> for tests/storybook HOT 14
- StackActions.popToRouteName(routeName) HOT 2
- Alternative API for defining navigators HOT 12
- how to send navigation events between peer navigators? HOT 4
- Deep linking with authentication
- How to hide tab bar item n react-navigation HOT 3
- Ability to show screens on top of native modals
- useNavigationParams hook HOT 1
- Add useMaterialTabsHeight HOT 1
- Typesafe Stack & Navigation HOT 1
- devTools prop HOT 5
- [RFC] TabView API change
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from rfcs.