2016-09-06 2 views
8

Derzeit habe ich Push und Pop eingerichtet mit NavigationStateUtils mit React Native/Redux. Aber wenn eine Taste, die die Push-Aktion auslöst, mehr als einmal gedrückt wird, erhalte ich den Fehler: should not push * route with duplicated key und * steht für route.key oder this.props.navKey.Wie erstellt man einen eindeutigen Schlüssel für NavigationStateUtils mit Push-Route in Native/Redux reagieren?

Was könnte die Ursache des Fehlers sein? Wie soll ich einen eindeutigen Schlüssel für jede einzelne Route mit NavigationStateUtils erstellen?

Das ist mein aufgebaut - Redux:

function mapStateToProps(state) { 
    return { 
    navigation: state.navReducer, 
    } 
} 

export default connect(
    mapStateToProps, 
    { 
    pushRoute: (route) => push(route), 
    popRoute:() => pop(), 
    } 
)(NavigationRoot) 

Mein Minderer (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 

Und diese Methoden behandeln Push- und Pop und wie Navigationsleiste zurück (pop) Taste Einrichtung:

_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} 
     /> 
    ) 
    } 

Und von Komponenten wie aufgerufen so:

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

EDIT Konsolprotokoll

enter image description here enter image description here

EDIT 2 Fortsetzung

enter image description here

EDIT 3 Slide Menu

enter image description here

Antwort

4

Debug Ihr Navigationsminderer wie folgt aus:

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

Aufgrund der Art und Weise NavigationStateUtils.push Werke (siehe here), es erfordert ein völlig neue Route, um zum Routenstapel zu gelangen. Aufgrund Ihres Navigationsflusses können Sie ihn nicht mehr verwenden, um nach Hause zurückzukehren. Sie müssen auch eine andere Funktion wie NavigationStateUtils.pop oder NavigationStateUtils.reset und andere verwenden (diese Datei durchsuchen). Sie sind jedoch nicht beschränkt auf nur die Funktionen in NavigationStateUtils, können Sie Ihre eigene Modifikation im Minderer definieren, aber Sie müssen sicherstellen, dass der Navigationszustand dieses Datenformat hat:

{ 
    // `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

Basierend auf Ihren Anforderungen in Ihren Kommentaren, muss jedes Mal, wenn Sie eine Schublade berühren, reset Ihr Navigationsroutenstapel diese Route als Ausgangspunkt haben, dann können Sie mit dem Schieben und Poppen beginnen.

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; 
    } 
} 

Als ein anderen Seite beachten, ich sehe, dass Ihre Anforderungen auf der Grundlage, wäre es wahrscheinlich eine gute Idee, react-native-router-flux versuchen verwenden, da Sie in der Lage sein werden, definieren Ihr routes, sub-routes, integrate with react-native-drawer und integrate with Redux.

+0

Entschuldigung, aber könnten Sie auf Ihrer Frage klären und zeigen, was Sie mit 'connect' Funktion bedeuten nicht Mapping" Versand "mit dem Code, den ich zur Verfügung gestellt? –

+0

Wie bist du auf die Idee gekommen: '{ pushRoute: (route) => push (route), popRoute:() => pop(), }'? aus der 'reakt-redux' Dokumentation? Es soll eine Funktionssignatur sein. – rclai

+0

https://medium.com/@dabit3/react-native-navigator-experimental-part-2-implementing-redux-c6acbf66eca1#.trrcjkhju Von hier aus –

Verwandte Themen