Closed domchristie closed 8 years ago
You are not supposed to be pushing 'scenes' that you don't want rendered onto the stack. In your case, renderScene
is called for both Login
and Dashboard
, and depending on how you set your index
, you'll be shown the scene at that index.
What you want is to have it render Login
, and upon successful login, call onNavigate with the appropriate action, and in your reducer, use NavigationStateUtils.push
to manipulate your state to include Dashboard
. Just like how you have it ^. Also, keep in mind that, unless you use NavigationView, your Login
component will be pushed off screen and will not be "garbage collected". Depending on what you're trying to achieve, you may or may not want this.
🍺
You are not supposed to be pushing 'scenes' that you don't want rendered onto the stack. In your case, renderScene is called for both Login and Dashboard, and depending on how you set your index, you'll be shown the scene at that index.
@jmurzy Thanks Jake, that’s great! I think I came to that conclusion eventually! I think part of my problem was that I was defining the structure of the navigation state tree, and then using that directly in my navigation components. I am now taking the approach of defining the structure separately and then slicing off the bits that are needed.
Thanks again
upon successful login, call onNavigate with the appropriate action
Interesting. At the moment, the full purpose of onNavigate
is a bit unclear to me. I’m using redux, and in my Login
component, I’m calling dispatch(navigateTo('Dashboard'))
in the componentWillReceiveProps
hook:
componentWillReceiveProps (nextProps) {
if (nextProps.session.user) this.dispatch(navigateTo('Dashboard'))
}
I’m only really using onNavigate
to handle the swiping gesture to go back:
<NavigationAnimatedView
navigationState={navigationState}
renderScene={renderScene}
onNavigate={() => { dispatch(navigateBack()) }}
/>
Perhaps I’m missing something again?
@domchristie : I'm not familiar with redux. The flux way of doing this will be purely reactive without using onNavigate
API.
class App extends React.Component {
constructor(props, context) {
super(props, context);
this.state = {
loggedIn: false,
navigationState: {
key: 'Root',
children: [
{key: 'Login'},
],
},
};
}
componentWillMount() {
AppStateStore.addListener(() => {
if (!this.state.loggedIn && AppStateStore.isLoggedIn()) {
this.setState({
loggedIn: true,
navigationState: {
key: 'Root',
children: [
{key: 'Login'}, // You may want to remove this since use is already logged in.
{key: 'DashBoard'},
],
},
});
}
});
}
render() {
return (
<AnimatedView
navigationState={this.state.navigationState}
renderScene={renderScene}
/>
);
}
}
@hedgerwang Thanks.
onNavigate
is a required prop of AnimatedView
, so would you just pass in an empty function?
@domchristie, Currently AnimatedView
needs an onNavigate
handler for things like the back button in the NavigationHeader, which may fire actions that need to be handled. If you don't have a header, or if you have a custom one, then you don't need it.
FWIW: part of my solution now includes maintaining two navigation states: one for the logged out case (for Log In / Sign Up routes), and other other for the logged in case (the rest of the app). I have two reducers to handle each state and combine them with redux’s combineReducers
. (Inspired in part by: http://blog.thebakery.io/react-native-experimental-navigation-with-redux/)
I have following state structure:
and a render method which looks something like:
The
'Dashboard'
(container) component requires some data which is requested on log in, however theAnimatedView
renders all it's scenes when it's initialised (even though they're not visible or "active"). In my case this will throw an error.How can I prevent a scene from rendering before it has the data it requires? It seems a bit daft to have to include conditionals for every component. I'm feel like I'm missing something here :/