React native 防止在React Navigation StackNavigator中出现重复屏幕
我需要防止StackNavigator的默认行为,即创建屏幕的多个副本并将其保存在内存中(并且具有随机卸载行为)。我只想要每个屏幕的一个实例 我已经按照下面的代码覆盖了路由器。它所做的是在导航时在堆栈中查找现有屏幕,如果存在,则将其移动到当前索引,并将其他所有内容混洗。它可能比要求的更复杂,但在我看来,你不应该乱搞当前的索引React native 防止在React Navigation StackNavigator中出现重复屏幕,react-native,react-navigation,React Native,React Navigation,我需要防止StackNavigator的默认行为,即创建屏幕的多个副本并将其保存在内存中(并且具有随机卸载行为)。我只想要每个屏幕的一个实例 我已经按照下面的代码覆盖了路由器。它所做的是在导航时在堆栈中查找现有屏幕,如果存在,则将其移动到当前索引,并将其他所有内容混洗。它可能比要求的更复杂,但在我看来,你不应该乱搞当前的索引 const AppNavigator = StackNavigator(Routes, {}); //move thi
const AppNavigator = StackNavigator(Routes, {});
//move this into routes.js if it works
const prevGetStateForAction = AppNavigator.router.getStateForAction;
AppNavigator.router = {
...AppNavigator.router,
getStateForAction(action, state) {
//check if route is already on stack and go to it instead of adding a new item on stack
//NOTE: This will break things like being able to have push notification messages on the same route but different messages and being able to go back through them
//if that becomes a problem just opt out for certain route names eg if(action.routeName == "Messages") return prevGetStateForAction(aciton,state)
if(state && action.type == 'Navigation/NAVIGATE' && state.routes !== undefined ) {
//console.log("getStateForAction state",state,"action,",action);
var i = -1;
//try find the route in the stack
for(var c =0; c < state.routes.length; c++) {
if(state.routes[c].routeName == action.routeName) {
i = c;
break;
}
}
//found it but we're already there so do nothing as we're trying to navigate to ourselves
if(i == state.index)
return null;
//didn't find it - add screen to stack - ie call default action
if(i == -1)
return prevGetStateForAction(action,state);
//found it - move it to just after index and increment index - i think
console.log("stacknavigator is trying to duplicate route - moving back to previous route");
var route = state.routes[i];
var routes = state.routes.splice(i,1);
//you've just moved the item that index was pointing at if it was greater than where our item was
var newIndex = 0;
if(state.index > i)
newIndex = state.index -1;
else
newIndex = state.index;
//index was at the end so we just take the array and add our item at the end - no slices needed
if(state.index == state.routes.length -1)
var routes = [ ...routes, route];
else
var routes = [
...state.routes.slice(0,newIndex+1),
route,
...state.routes.slice(state.index+1)
];
return {
...state,
routes: routes,
index: newIndex
}
}
return prevGetStateForAction(action,state);
}
const-AppNavigator=StackNavigator(路由,{});
//如果可行,请将其移动到routes.js中
const prevGetStateForAction=AppNavigator.router.getStateForAction;
AppNavigator.router={
…AppNavigator.router,
getStateForAction(操作、状态){
//检查路由是否已在堆栈上,并转到它,而不是在堆栈上添加新项
//注意:这将打破类似于在同一路由上有推送通知消息但有不同消息以及能够通过它们返回的功能
//如果出现问题,只需选择退出某些路由名称,例如if(action.routeName==“Messages”)返回prevGetStateForAction(aciton,state)
if(state&&action.type==“导航/导航”&&state.routes!==未定义){
//log(“getStateForAction state”,state,“action”,action);
var i=-1;
//尝试在堆栈中查找路由
对于(var c=0;ci)
newIndex=state.index-1;
其他的
newIndex=state.index;
//索引位于末尾,因此我们只需获取数组并在末尾添加项,无需切片
if(state.index==state.routes.length-1)
var routes=[…routes,route];
其他的
变量路由=[
…state.routes.slice(0,newIndex+1),
路线,,
…state.routes.slice(state.index+1)
];
返回{
……国家,
路线:路线,,
索引:newIndex
}
}
返回prevGetStateForAction(操作,状态);
}
它工作了相当长的一段时间(例如,你可以在不创建副本的情况下愉快地四处导航)但最终失败了,我无法找出原因-当dupe被点击时,你可以看到我的console.log调用,但它从未被点击-代码正在运行,但。这可能是代码中的错误,但我觉得这更可能是我缺少的反应导航行为。可能是导航/后退和后退按钮行为我没有考虑在内
是否有人可以更正我的代码或提供另一种方法来防止堆栈中出现重复屏幕
编辑-因为我无法将代码放入注释中
我有另一个想法,在我看来,我可能不应该试图保持索引不变,因为我的屏幕现在将在堆栈的末尾
无论如何,它似乎已经解决了问题,因为我一直无法复制屏幕
const AppNavigator = StackNavigator(Routes, {});
//move this into routes.js if it works
const prevGetStateForAction = AppNavigator.router.getStateForAction;
AppNavigator.router = {
...AppNavigator.router,
getStateForAction(action, state) {
//check if route is already on stack and go to it instead of adding a new item on stack
//NOTE: This will break things like being able to have push notification messages on the same route but different messages and being able to go back through them
//if that becomes a problem just opt out for certain route names eg if(action.routeName == "Messages") return prevGetStateForAction(aciton,state)
if(state && action.type == 'Navigation/NAVIGATE' && state.routes !== undefined ) {
//console.log("getStateForAction state",state,"action,",action);
var i = -1;
//try find the route in the stack
for(var c =0; c < state.routes.length; c++) {
if(state.routes[c].routeName == action.routeName) {
i = c;
break;
}
}
//found it but we're already there so do nothing as we're trying to navigate to ourselves
if(i == state.index) {
console.log("getstateforaction() - you're trying to navigate to yourself!");
return null;
}
//didn't find it - add screen to stack - ie call default action
if(i == -1) {
console.log("getstateforaction() - no duplicate screen found");
return prevGetStateForAction(action,state);
}
//found it - move it to just after index and increment index - i think
console.log("stacknavigator is trying to duplicate route - moving back to previous route");
var route = state.routes[i];
var routes = state.routes;
routes.splice(i,1);
routes = [
...routes,
route
];
newIndex = routes.length-1;
return {
...state,
routes: routes,
index: newIndex
}
}
return prevGetStateForAction(action,state);
}
const-AppNavigator=StackNavigator(路由,{});
//如果可行,请将其移动到routes.js中
const prevGetStateForAction=AppNavigator.router.getStateForAction;
AppNavigator.router={
…AppNavigator.router,
getStateForAction(操作、状态){
//检查路由是否已在堆栈上,并转到它,而不是在堆栈上添加新项
//注意:这将打破类似于在同一路由上有推送通知消息但有不同消息以及能够通过它们返回的功能
//如果出现问题,只需选择退出某些路由名称,例如if(action.routeName==“Messages”)返回prevGetStateForAction(aciton,state)
if(state&&action.type==“导航/导航”&&state.routes!==未定义){
//log(“getStateForAction state”,state,“action”,action);
var i=-1;
//尝试在堆栈中查找路由
对于(var c=0;c