New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Feature Request] Can stack router have replace
like History API?
#802
Comments
+1 , agree with you, the REPLACE pattern is very useful! |
I just think that : it will empty the stack,but all objects you have registered before are also here,so you can use them as usual. |
@justbettereveryday Could you explain more about how to get all objects you have registered? |
I also use replace in my app and I think it's a good idea to have an action like that. Until that gets done, I have used a workaround of passing my own flag into a navigate action, and when I detect it, I manually kick the last route from state before doing getStateForAction. It seems to work, with a little problem of missing the animation. |
@joonhocho
|
I think it is a good idea to have What if we added a Lets track this issue as a part of #135, where we plan on adding a key to the navigate action |
For anyone else that comes along this issue I'm currently using the following solution. I specify a new action type inside the const prevGetStateForActionHomeStack = HomeStack.router.getStateForAction;
HomeStack.router = {
...HomeStack.router,
getStateForAction(action, state) {
if (state && action.type === 'ReplaceCurrentScreen') {
const routes = state.routes.slice(0, state.routes.length - 1);
routes.push(action);
return {
...state,
routes,
index: routes.length - 1,
};
}
return prevGetStateForActionHomeStack(action, state);
},
}; replaceScreen = () => {
const { locations, position } = this.props.navigation.state.params;
this.props.navigation.dispatch({
key: 'NearMeMap',
type: 'ReplaceCurrentScreen',
routeName: 'NearMeMap',
params: { locations, position },
});
}; I also put together a short video walking through this code, if that would help anyone. |
@spencercarli Awesome! Do you know how to animate replace action by any chance? |
@joonhocho I don't - do you have an example of what kind of animation you're thinking of? |
@spencercarli probably the base animation it has when navigating to a screen :p |
@spencercarli - I tried your solution, and it's not woking for me. I check Thoughts? |
@timscott I had to change the code a bit and it's working correctly.
Modified it directly:
You can see this direct modification mentioned in the docs for routers: https://reactnavigation.org/docs/routers/ |
In case it's helpful, I tried a different approach to a new action name to try and not mess around as much as possible with the normal implementation of When I navigated, I did this: navigation.navigate("ScreenName", { replaceRoute: true }); And then looked for that in the /* @flow */
import type {
NavigationAction,
NavigationState
} from "react-navigation/lib/TypeDefinition";
import NavigationActions from "react-navigation/lib/NavigationActions";
const updateStackRouter = function(StackNavigator: any) {
// generally defer to the "real" one
const parentGetStateForAction = StackNavigator.router.getStateForAction;
StackNavigator.router.getStateForAction = function(
action: NavigationAction,
inputState?: ?NavigationState
): ?NavigationState {
const state: ?NavigationState = parentGetStateForAction(action, inputState);
// fix it up if applicable
if (state && action.type === NavigationActions.NAVIGATE) {
if (action.params && action.params.replaceRoute) {
delete action.params.replaceRoute;
if (state.routes.length > 1 && state.index > 0) {
const oldIndex = state.index - 1;
// remove one that we are replacing
state.routes.splice(oldIndex, 1);
// index now one less
state.index = oldIndex;
}
}
}
return state;
};
};
export default updateStackRouter; |
Any movement here?.. just trying to do the same thing i did in |
@cyberdelphos' corrected method works great with the latest (beta.11) version of the library. Thanks for posting that update here @cyberdelphos! 🙏 You saved me hours trying to figure out what's wrong with @spencercarli's original method. |
I really liked @bleonard approach to the problem. I would love to see more helpers using this method, or having this level of simplicity such as reset. |
Not sure if that's gonna work with nested navigators though |
I haven't tried with nested, but it's only modifying the one stack that it's dealing with, so I would think it was ok. |
Both @spencercarli and @bleonard solutions loses the transition animation, is there any way to preserve it? Thanks |
Doesn't work with nested routes unfortunately |
@spencercarli thanks for sharing the code. Can you please help to understand how this would work with nested navigators? I am getting #1127 when I try this with nested routes |
I was exploring this out a bit more and here are few things which one should be aware before implementing:-
To avoid point 3 I had changed my code to following:-
|
@jinxac what about nested routes? Any solution? |
@gianpieroc i had used nested-routes when i started the porting of code to react-navigation but after seeing the open issues related to nesting i completing avoided it and created a single stack navigator itself. So currently no solution for nested routes either. |
For those who have nested do the following (note pullat is a lodash function but basically you just need to remove second to last element) const prevGetStateForActionMainStack = MainStack.router.getStateForAction;
MainStack.router.getStateForAction = (action, state) => {
if (state && action.type === "ReplaceCurrentScreen") {
action.type = "Navigation/NAVIGATE"; // change it to navigate to get the next state
let newState = prevGetStateForActionMainStack(action, state); // Let default run because nesting hard to build
pullAt(newState.routes, [newState.routes.length - 2]); // pull out second to last element
newState.index = newState.index - 1;
return newState;
}
return prevGetStateForActionMainStack(action, state);
}; |
@brentvatne still no example in there :( |
@pacozaa, feel free to add a link to the navigation playground code in this repository which demonstrates the replace functionality, and send a pull request for that 🙂 |
ExceptionsManager.js:63 navigation.state.routes[2].key "scene_OrderList" conflicts with another route! |
Can
|
Has this been implemented into react-navigation, eventually, so I don't have to hack around the API to get this to work? |
I think
replace
is very common routing pattern that html history api also has it.You don't always want to
push
to stack, but sometimes want to replace it with or without animation instead of going through pop and push (two animation phases).According to doc, calling
reset
will empty your stack, but that's not how replace should work.It should work like so:
state: a -> b -> c
action: c calls
replace(d)
result: a -> b -> d
state: a -> b -> c
action: b calls
replace(d)
result: a -> d
The text was updated successfully, but these errors were encountered: