GithubHelp home page GithubHelp logo

Comments (35)

JustinNothling avatar JustinNothling commented on April 19, 2024 7

Ok So I have a solution:

You need to add an index of 0 to your reset action:
dispatch({type: 'Reset', index: 0, actions: [{ type: 'Navigate', routeName:'Home'}]})

Haven't yet figured out how to run this only at the end of a transition - think you may need to use the Transitioner component

from react-navigation.

ericvicenti avatar ericvicenti commented on April 19, 2024 4

@JustinNothling, I would probably want to prevent the gesture. But I don't think there is a way to do that currently.

It might make sense to add a gesturesEnabled screen navigation option, so a screen can toggle gestures based on the route.

from react-navigation.

rohit-ravikoti avatar rohit-ravikoti commented on April 19, 2024 4

That worked! Thanks! 😜

from react-navigation.

JustinNothling avatar JustinNothling commented on April 19, 2024 3

@ericvicenti we're in agreement about the reset helper.

How would you go about structuring a simple login/logout using react-navigation? At the moment pushing a home route onto login allows users to goBack to login using gestures (which isn't ideal). Would you reset the stack or would you prevent the gesture?

from react-navigation.

mmazzarolo avatar mmazzarolo commented on April 19, 2024 3

@JustinNothling I have, but I had to tweak a bit the code...

@satya164 I'm on master and by reading the docs it seems that for dispatching a reset action I need all I have to do is the following:

const actionToDispatch = NavigationActions.reset({
  actions: NavigationActions.navigate({ routeName })
})
this.props.navigation.dispatch(actionToDispatch)

Which doesn't work.
The following does though:

const actionToDispatch = NavigationActions.reset({
  index: 0,
  actions: [NavigationActions.navigate({ routeName })] // Array!
})
this.props.navigation.dispatch(actionToDispatch)

Is this the correct way to reset the stack? Am I just misunderstanding the docs? Let me know, I'd like to PR with a "clear way" for resetting the stack.

from react-navigation.

ericvicenti avatar ericvicenti commented on April 19, 2024 2

@JustinNothling, good point, we don't expose Transitioner's onTransitionEnd through CardStack or StackNavigator. That hasn't come up yet! Want to submit a PR?

I'm on the fence about adding a reset helper because it doesn't always make sense for a child component to be aware of the application around it. Pretty soon people will want to add popAndReplace and pushTwiceAndJumpBack or whatever :-) . The replace option won't always be practical, because the screen can't see the whole navigation state (nor should it! you don't want every screen to re-render when one of their state changes). Instead, to support complicated navigation behaviors, you may want to override behavior on the router: https://reactnavigation.org/docs/routers/#Custom-Navigation-Actions

from react-navigation.

CoteViande avatar CoteViande commented on April 19, 2024 2

I fixed my issue by restraining myself to only one level of depth in my navigation, without deep linking.

const MainScreenNavigator = TabNavigator({
  Recent: { screen: RecentScreen },
  Logout: { screen: LogoutScreen },
})

const AppNavigator = StackNavigator({
  FacebookAuthentication: { screen: FacebookAuthScreen },
  EmailAuthentication: { screen: EmailAuthScreen },
  Home: { screen: MainScreenNavigator },
})

from react-navigation.

markflorisson avatar markflorisson commented on April 19, 2024 2

@Paul-Todd hi Paul, this is the code I use in my Home screen:

class HomeScreen extends Component {
    redirectKey = null

    render = () => {
        const { redirectRoute, redirectKey, redirectParams } = this.params
        if (redirectRoute && redirectKey != this.redirectKey) {
            this.redirectKey = redirectKey
            setTimeout(() => {
                this.props.navigation.navigate(redirectRoute, redirectParams)
            }, 0)
        }

        return (
            <HomeView
                navigation={this.props.navigation}
                />
        )
    }
}

Putting the redirect logic in componentDidMount doesn't work, as componentDidMount is only called once on the home screen (not sure when it is unmounted).

From another page I then reset to the home screen as follows:

import { NavigationActions } from 'react-navigation'
import shortid from 'shortid'

const resetRoute = (navigation, params) => {
    navigation.dispatch(
        NavigationActions.reset({
            index: 0,
            actions: [
                NavigationActions.navigate({
                    routeName: 'Home',
                    params: params,
                }),
            ],
        }),
    )
}

class SomeOtherScreen extends Component {
    handlePress = () => {
        resetRoute(this.props.navigation, {
            redirectRoute: 'ScreenToRedirectTo',
            redirectKey: shortid(),
            redirectParams: {
                ... params for ScreenToRedirectTo ...
            },
        })
    }

    ...
}

NOTE: the shortid() is necessary in order to only perform the redirect once (e.g. if the user pressed "back" to go back to the home screen we no longer wish to perform a redirect).

Disclaimer: This code is pretty terrible, I don't recommend using it if you can avoid it :)

from react-navigation.

markflorisson avatar markflorisson commented on April 19, 2024 1

Awesome, that works! Maybe it would be useful to have a 'reset' function on the 'navigation' object?

from react-navigation.

JustinNothling avatar JustinNothling commented on April 19, 2024 1

Hey has anyone got the new code on for reset in the docs to work?
https://reactnavigation.org/docs/navigators/navigation-prop

import { NavigationActions } from 'react-navigation'

NavigationActions.reset({
  actions: NavigationActions.navigate({ routeName: 'Profile'}),
})

I'm getting an error saying reset is undefined.

from react-navigation.

markflorisson avatar markflorisson commented on April 19, 2024 1

Ok so the issue is not necessarily with the reducers so much as how to use the reset action. What you need to do is make sure you set the correct index. This works for me:

        this.props.navigation.dispatch(
            NavigationActions.reset({
                index: 1,
                actions: [
                    NavigationActions.navigate({
                        routeName: 'Home',
                    }),
                    NavigationActions.navigate({
                        routeName: 'Bar',
                        params: {
                            ...,
                        },
                    }),
                ],
            }),
        )

Setting the 'index' as part of the 'navigate' doesn't seem to work.

from react-navigation.

JustinNothling avatar JustinNothling commented on April 19, 2024

Hey Mark, I got the same problem on my end so I'll let you know if I come up with a solution.

from react-navigation.

nebula-ai avatar nebula-ai commented on April 19, 2024

You might fine this useful. It is a variation of the tutorial where I have a login screen and then a logout function under the Options right element of the RecentChatsScreen which will get you back to the original login screen.

import React from 'react';
import {
AppRegistry,
Text,
View,
Button
} from 'react-native';
import { StackNavigator, TabNavigator } from 'react-navigation';

class SigninScreen extends React.Component {
static navigationOptions = {
title: 'Sign In',
};
render() {
const { navigate } = this.props.navigation;
return (

Sign In
<Button
onPress={() => navigate('Home')}
title="Sign In"
/>

);
}
}

class OptionsScreen extends React.Component {
static navigationOptions = {
title: 'Options',
};
render() {
const { navigate } = this.props.navigation;
const { dispatch } = this.props.navigation;
return (

Options!
<Button
onPress={() => {dispatch({type:'Reset', actions: [{ type: 'Navigate', routeName: 'Signin'}], index: 0 })}}
title="Logout"
/>

);
}
}

class RecentChatsScreen extends React.Component {
static navigationOptions = {
// Nav options can be defined as a function of the navigation prop:

header: (navigation) => ({
  title: 'Recent Chats',
  right: <Button title='Options' onPress={() => navigation.navigate('Options')} />
}),

};

render() {
return (

List of recent chats
<Button
onPress={() => this.props.navigation.navigate('Chat', { user: 'Lucy' })}
title="Chat with Lucy"
/>

)
}
}

class AllContactsScreen extends React.Component {
render() {
return (

List of recent chats
<Button
onPress={() => this.props.navigation.navigate('Chat', { user: 'Jane' })}
title="Chat with Jane"
/>

)

}
}

const MainScreenNavigator = TabNavigator({
Recent: { screen: RecentChatsScreen },
All: { screen: AllContactsScreen },
});

MainScreenNavigator.navigationOptions = {
title: 'My Chats',
};

class ChatScreen extends React.Component {
static navigationOptions = {
// Nav options can be defined as a function of the navigation prop:
title: ({ state }) => Chat with ${state.params.user},
};
render() {
// The screen's current route is passed in to props.navigation.state:
const { params } = this.props.navigation.state;
return (

Chat with {params.user}

);
}
}

const TheApp = StackNavigator({
Signin: { screen: SigninScreen},
Home: { screen: MainScreenNavigator },
Chat: { screen: ChatScreen },
Options: { screen: OptionsScreen },

});

AppRegistry.registerComponent('exp', () => TheApp);

from react-navigation.

CoteViande avatar CoteViande commented on April 19, 2024

I have tried to implement Login/Logout using Reset action. However, with NestedNavigators I get the following error:

There is no route defined for key Home. Must be one of: 'FacebookAuthentication','EmailAuthentication'

I run the redux implemantation, like in the docs, so in a middleware, I run:

// middleware
if (prevState.isAuthenticated !== nextState.isAuthenticated) {
    const nextScreen = nextState.isAuthenticated
      ? 'Home'
      : 'Authenticate'
    dispatch({
      type: 'Reset',
      index: 0,
      actions: [{
        type: 'Navigate',
        routeName: nextScreen,
      }],
    })
  }

Here is my reduced Navigator config:

// Navigator settings
const AuthenticateNavigator = StackNavigator({
  FacebookAuthentication: { screen: FacebookAuthScreen },
  EmailAuthentication: { screen: EmailAuthScreen },
})

const MainScreenNavigator = TabNavigator({
  Recent: { screen: RecentScreen },
  Logout: { screen: LogoutScreen },
})

const AppNavigator = StackNavigator({
  Authenticate: { screen: AuthenticateNavigator },
  Home: { screen: MainScreenNavigator },
})

from react-navigation.

markflorisson avatar markflorisson commented on April 19, 2024

Actually, the reset action doesn't seem to work properly. If I reset to 'Home' it works, but if I add additional actions to the reset it doesn't navigate to the right screen and seems to "freeze" (no button presses get registered). This is the code:

        dispatch({
            type: 'Reset',
            index: 0,
            actions: [
                {
                    type: 'Navigate',
                    routeName: 'Home',
                },
                {
                    type: 'Navigate',
                    routeName: 'Items',
                },
            ],
        })

This is the state:

{ action: 
  { type: 'Reset',
    index: 0,
    actions: 
     [ { type: 'Navigate', routeName: 'Home' },
       { type: 'Navigate', routeName: 'Items' } ] },
 newState: 
  { index: 0,
    routes: 
     [ { routeName: 'Home', key: 'Init0' },
       { routeName: 'Items', key: 'Init1' } ] },
 lastState: 
  { index: 3,
    routes: 
     [ { routeName: 'Home', key: 'Init' },
       { type: 'Navigate',
         routeName: 'Items',
         params: undefined,
         action: undefined,
         key: 'id-1485774310007-0' },
       { type: 'Navigate',
         routeName: 'Menu',
         params: undefined,
         action: undefined,
         key: 'id-1485774310007-1' },
       { type: 'Navigate',
         routeName: 'Checkout',
         params: undefined,
         action: undefined,
         key: 'id-1485774310007-2' } ] } }

from react-navigation.

markflorisson avatar markflorisson commented on April 19, 2024

The workaround that works for me is to set up deep linking and use Linking.openURL(...). However, this will only work well if you are happy with a navigation stack of 1 level deep (where the back arrow points back to home).

from react-navigation.

lslima91 avatar lslima91 commented on April 19, 2024

Maybe I'm misunderstanding, but shouldn't it be possible to simply dispatch a goBack, if you want a simple pop?
{type: 'goBack', ...}

Or do we need to manually dispatch reset actions in this case?

from react-navigation.

elliottjro avatar elliottjro commented on April 19, 2024

@lslima91 a goBack() only works if you navigated into the second screen. In the case where eg: user was already logged in and they press logout -> this should call reset and not goBack because we never went from logged out screen to home screen.

-> At least i think this is the functionality of goBack() please correct if I'm wrong

ps: I am also running into this issue, it looks like a second action cannot be sent to the child router.

from react-navigation.

lslima91 avatar lslima91 commented on April 19, 2024

@elliottjro The thing is, I'm not able to dispatch a type: goBack action. I have to manually dispatch a reset with the correct routename.

from react-navigation.

elliottjro avatar elliottjro commented on April 19, 2024

@lslima91 the goBack() method isn't an available type to be sent via dispatch(). You have to call goBack() directly on the navigation prop. reference

Example:

<Button onPress={ () => this.props.navigation.goBack() } />

from react-navigation.

lslima91 avatar lslima91 commented on April 19, 2024

nvm, I have to dispatch {type:'Back'}, this new PR makes things much better imo #120

from react-navigation.

satya164 avatar satya164 commented on April 19, 2024

@JustinNothling are using the version from master?

from react-navigation.

satya164 avatar satya164 commented on April 19, 2024

the second one is correct. seems there's an error in the doc. willing to send a PR?

from react-navigation.

rohit-ravikoti avatar rohit-ravikoti commented on April 19, 2024

@mmazzarolo,
this.props.navigation.dispatch doesn't seem to be doing anything on my app. To give some context, I didn't integrate react-navigation with a redux store.

from react-navigation.

mmazzarolo avatar mmazzarolo commented on April 19, 2024

Copy-paste from #156

@rohit-ravikoti the snippet you pasted is not using redux, it is just plain react-navigation (which uses a pattern similar to the one used in redux).
I'm using it right now and it is working correctly.

Make sure you're using the master branch though!

  1. Remove your current version of react-navigation: npm uninstall react-navigation
  2. Add the master branch one: npm install --save https://github.com/react-community/react-navigation.git
  3. Restart the packager npm run start -- --reset-cache
  4. Fire up your emulator

Let me know if it works :)

from react-navigation.

elliottjro avatar elliottjro commented on April 19, 2024

Hey all, it looks like this issue is fixed but original issue was using the reset action along with a nested navigation action.

@markflorisson can you confirm this is the case else close current issue.

from react-navigation.

markflorisson avatar markflorisson commented on April 19, 2024

Hi @elliottjro, yeah the refactor looks great but nested navigation actions still don't seem to work:

        this.props.navigation.navigate(
            NavigationActions.reset({
                index: 0,
                actions: [
                    NavigationActions.navigate({
                        routeName: 'Home',
                    }),
                    NavigationActions.navigate({
                        routeName: 'Items',
                        params: {
                            ...
                        },
                    }),
                ],
            })
        )

from react-navigation.

markflorisson avatar markflorisson commented on April 19, 2024

Or do we have to nest the second 'navigate' action inside the first one, like so?

        this.props.navigation.navigate(
            NavigationActions.reset({
                index: 0,
                actions: [
                    NavigationActions.navigate({
                        routeName: 'Home',
                        actions: [
                            NavigationActions.navigate({
                                routeName: 'Items',
                                params: {
                                    ...
                                },
                            }),
                        ]
                    }),
                ],
            })
        )

from react-navigation.

markflorisson avatar markflorisson commented on April 19, 2024

BTW the most reliable way to work around is it to navigate to the 'Home' screen with a param, and then to do a 'navigate' from the Home screen to whereever you need to redirect. But it's a hassle and it involves an unnecessary rendering of the home screen.

from react-navigation.

ericvicenti avatar ericvicenti commented on April 19, 2024

@markflorisson, it can be hard to see what is going wrong exactly. Can you write a test for StackRouter.getStateForAction, and verify that the reset action works correctly? The failing test will make the bug super clear.

from react-navigation.

Paul-Todd avatar Paul-Todd commented on April 19, 2024

@markflorisson - do you have an example of navigation with the param? I am stuck in the way at the moment

from react-navigation.

markflorisson avatar markflorisson commented on April 19, 2024

@ericvicenti Will give it a go, thanks!

from react-navigation.

markflorisson avatar markflorisson commented on April 19, 2024

(BTW: What is the reason for 'index'? Can the reducer not just take 'actions.length'?)

from react-navigation.

ericvicenti avatar ericvicenti commented on April 19, 2024

Theoretically, I think index should be optional and would default to actions.length, but we don't have that feature right now. PR would be accepted for it.

Closing this out because it seems like everything is working. And I'll continue to think about how the API could be improved.

from react-navigation.

davebro avatar davebro commented on April 19, 2024

@CoteViande This solved ALL my navigation problems!

from react-navigation.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo 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.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.