如何在React Native / Redux中使用推送路径为NavigationStateUtils创建唯一键?(How to create unique key for NavigationSta

系统教程 行业动态 更新时间:2024-06-14 16:58:30
如何在React Native / Redux中使用推送路径为NavigationStateUtils创建唯一键?(How to create unique key for NavigationStateUtils using push route in React Native/Redux?)

目前,我使用使用React Native / Redux的NavigationStateUtils来设置Push和Pop。 但是当触发Push动作的按钮不止一次被按下时,我得到这个错误: should not push * route with duplicated key *代表route.key或this.props.navKey 。

什么可能是错误的原因? 我应该如何使用NavigationStateUtils为每个单独的路线创建唯一的密钥?

这是我的设置 - Redux:

function mapStateToProps(state) { return { navigation: state.navReducer, } } export default connect( mapStateToProps, { pushRoute: (route) => push(route), popRoute: () => pop(), } )(NavigationRoot)

我的reducer( navReducer.js ):

const initialState = { index: 0, key: 'root', routes: [{ key: 'login', title: 'Login', component: Login, direction: 'horizontal', }] } function navigationState (state = initialState, action) { switch(action.type) { case PUSH_ROUTE: if (state.routes[state.index].key === (action.route && action.route.key)) return state return NavigationStateUtils.push(state, action.route) case POP_ROUTE: if (state.index === 0 || state.routes.length === 1) return state return NavigationStateUtils.pop(state) default: return state } } export default navigationState

这些方法处理推送和弹出以及导航栏返回(弹出)按钮的设置方式:

_renderScene (props) { const { route } = props.scene return ( <route.component _handleNavigate={this._handleNavigate.bind(this)} {...route.passProps} actions={this.props}/> ) } _handleBackAction() { if (this.props.navigation.index === 0) { return false } this.props.popRoute() return true } _handleNavigate(action) { switch (action && action.type) { case 'push': this.props.pushRoute(action.route) return true case 'back': case 'pop': return this._handleBackAction() default: return false } } renderOverlay = (sceneProps) => { if(0 < sceneProps.scene.index) { return ( <NavigationHeader {...sceneProps} renderLeftComponent={() => { switch(sceneProps.scene.route.title){ case 'Home': return ( <TouchableHighlight onPress={() => this._handleBackAction()}> <Text}>X</Text> </TouchableHighlight> ) } } } /> ) } } render() { return ( <NavigationCardStack direction={this.props.navigation.routes[this.props.navigation.index].direction} navigationState={this.props.navigation} onNavigate={this._handleNavigate.bind(this)} renderScene={this._renderScene} renderOverlay={this.renderOverlay} /> ) }

并由组件调用,如下所示:

const route = { home: { type: 'push', route: { key: 'home', title: 'Home', component: Home, direction: 'vertical', } } }

编辑控制台日志

编辑2继续

编辑3幻灯片菜单

Currently I have both Push and Pop set up using NavigationStateUtils using React Native/Redux. But when a button that triggers the Push action is pressed more than once, I get the error: should not push * route with duplicated key and * representing route.key or this.props.navKey.

What may be the cause of the error? How should I go about creating a unique key for each individual route using NavigationStateUtils?

This is my set up - Redux:

function mapStateToProps(state) { return { navigation: state.navReducer, } } export default connect( mapStateToProps, { pushRoute: (route) => push(route), popRoute: () => pop(), } )(NavigationRoot)

My reducer (navReducer.js):

const initialState = { index: 0, key: 'root', routes: [{ key: 'login', title: 'Login', component: Login, direction: 'horizontal', }] } function navigationState (state = initialState, action) { switch(action.type) { case PUSH_ROUTE: if (state.routes[state.index].key === (action.route && action.route.key)) return state return NavigationStateUtils.push(state, action.route) case POP_ROUTE: if (state.index === 0 || state.routes.length === 1) return state return NavigationStateUtils.pop(state) default: return state } } export default navigationState

And these methods handle push and pop and how navigation bar back (pop) button is set up:

_renderScene (props) { const { route } = props.scene return ( <route.component _handleNavigate={this._handleNavigate.bind(this)} {...route.passProps} actions={this.props}/> ) } _handleBackAction() { if (this.props.navigation.index === 0) { return false } this.props.popRoute() return true } _handleNavigate(action) { switch (action && action.type) { case 'push': this.props.pushRoute(action.route) return true case 'back': case 'pop': return this._handleBackAction() default: return false } } renderOverlay = (sceneProps) => { if(0 < sceneProps.scene.index) { return ( <NavigationHeader {...sceneProps} renderLeftComponent={() => { switch(sceneProps.scene.route.title){ case 'Home': return ( <TouchableHighlight onPress={() => this._handleBackAction()}> <Text}>X</Text> </TouchableHighlight> ) } } } /> ) } } render() { return ( <NavigationCardStack direction={this.props.navigation.routes[this.props.navigation.index].direction} navigationState={this.props.navigation} onNavigate={this._handleNavigate.bind(this)} renderScene={this._renderScene} renderOverlay={this.renderOverlay} /> ) }

And called by components like so:

const route = { home: { type: 'push', route: { key: 'home', title: 'Home', component: Home, direction: 'vertical', } } }

EDIT console log

EDIT 2 Continuation

EDIT 3 Slide Menu

最满意答案

像这样调试你的导航缩小器:

function navigationState (state = initialState, action) { switch(action.type) { case PUSH_ROUTE: console.log('action', action); if (state.routes[state.index].key === (action.route && action.route.key)) return state const newNavigationState = NavigationStateUtils.push(state, action.route); console.log('newNavigationState', newNavigationState); return newNavigationState; case POP_ROUTE: if (state.index === 0 || state.routes.length === 1) return state return NavigationStateUtils.pop(state) default: return state } }

编辑

由于NavigationStateUtils.push工作方式(请参见此处 ),它需要一个全新的路由来推送到路由堆栈。 根据您的导航流程,您不能再次使用它来回家,您必须使用不同的功能,例如NavigationStateUtils.pop或NavigationStateUtils.reset以及其他功能(探索该文件)。 但是,您并不仅限于NavigationStateUtils的函数,您可以在Reducer中定义自己的修改,但需要确保导航状态具有以下数据格式:

{ // `routes` needs to be an array of objects and each object // needs to have a unique `key` property routes: [{ key: 'anything', // must be unique in this `routes` array ...anyOtherData }], // `index` is required, and has to be a number that refers // to the index of the route in the routes array that is active index: 1, }

编辑

根据您在评论中的要求,每当您点击一个抽屉项目时,都需要重新设置以该路线为起点的导航路线堆栈,然后才能开始推送和弹出。

function navigationState (state = initialState, action) { switch(action.type) { case PUSH_ROUTE: if (state.routes[state.index].key === (action.route && action.route.key)) return state return NavigationStateUtils.push(state, action.route) case POP_ROUTE: if (state.index === 0 || state.routes.length === 1) return state return NavigationStateUtils.pop(state) case DRAWER_ITEM_PRESS: // `action.route` is simply the route object of the drawer item you pressed return NavigationStateUtils.reset(state, [action.route], 0); default: return state; } }

另一方面我注意到,根据你的要求,尝试使用react-native-router-flux可能是一个好主意,因为你可以定义你的路由 , 子路由 , 与react-native-drawer并与Redux集成 。

Debug your navigation reducer like this:

function navigationState (state = initialState, action) { switch(action.type) { case PUSH_ROUTE: console.log('action', action); if (state.routes[state.index].key === (action.route && action.route.key)) return state const newNavigationState = NavigationStateUtils.push(state, action.route); console.log('newNavigationState', newNavigationState); return newNavigationState; case POP_ROUTE: if (state.index === 0 || state.routes.length === 1) return state return NavigationStateUtils.pop(state) default: return state } }

EDIT

Because of the way NavigationStateUtils.push works (see here), it requires a completely new route to push to the route stack. Based on your navigation flow, you cannot use it again to go back home, you have to use a different function like NavigationStateUtils.pop or NavigationStateUtils.reset and others as well (explore that file). However, you are not limited to just the functions in NavigationStateUtils, you can define your own modification in the reducer but you need to make sure the navigation state has this data format:

{ // `routes` needs to be an array of objects and each object // needs to have a unique `key` property routes: [{ key: 'anything', // must be unique in this `routes` array ...anyOtherData }], // `index` is required, and has to be a number that refers // to the index of the route in the routes array that is active index: 1, }

EDIT

Based on your requirements in your comments, every time your hit a drawer item, it needs to reset your navigation route stack having that route as your starting point, then you can start pushing and popping.

function navigationState (state = initialState, action) { switch(action.type) { case PUSH_ROUTE: if (state.routes[state.index].key === (action.route && action.route.key)) return state return NavigationStateUtils.push(state, action.route) case POP_ROUTE: if (state.index === 0 || state.routes.length === 1) return state return NavigationStateUtils.pop(state) case DRAWER_ITEM_PRESS: // `action.route` is simply the route object of the drawer item you pressed return NavigationStateUtils.reset(state, [action.route], 0); default: return state; } }

As another side note, I see that based on your requirements, it would probably be a good idea to try using react-native-router-flux because you will be able to define your routes, sub-routes, integrate with react-native-drawer and integrate with Redux.

更多推荐

本文发布于:2023-04-15 03:26:00,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/dzcp/a23b3a4671f2743c673fcad18e03bad0.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:一键   路径   如何在   NavigationStateUtils   Native

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!