2016-09-06 5 views
8

Obecnie mam zarówno Push i Pop skonfigurować za pomocą NavigationStateUtils przy użyciu React Native/Redux. Ale gdy przycisk uruchamiający akcję Push zostanie naciśnięty więcej niż jeden raz, pojawia się błąd: should not push * route with duplicated key i * reprezentujący route.key lub this.props.navKey.Jak utworzyć klucz unikalny dla obiektu NavigationStateUtils za pomocą funkcji push route w React Native/Redux?

Co może być przyczyną błędu? Jak mam utworzyć unikalny klucz dla każdej pojedynczej trasy, używając NavigationStateUtils?

To jest mój set up - Redux:

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

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

Mój reduktor (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 

A te metody obsługi Push i Pop oraz jak pasek nawigacyjny z powrotem (pop) przycisku skonfigurowano:

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

I wywołane przez takie komponenty jak tak:

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

dziennika konsola EDIT

enter image description here enter image description here

EDIT 2 Kontynuacja

enter image description here

EDIT 3 Przesuń Menu

enter image description here

Odpowiedz

4

debugowania reduktor nawigacji tak:

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

ze względu na sposób NavigationStateUtils.push robót (zob here), wymaga zupełnie nowa droga do wypchnięcia na stos trasy. Opierając się na twoim strumieniu nawigacji, nie możesz go użyć ponownie, aby wrócić do domu, musisz użyć innej funkcji, takiej jak NavigationStateUtils.pop lub NavigationStateUtils.reset i innych (sprawdź ten plik). Jednak nie są ograniczone tylko do tych funkcji w NavigationStateUtils można zdefiniować własną modyfikację reduktora ale trzeba upewnić się, że stan nawigacja ma ten format danych:

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

Zgodnie z Twoimi wymaganiami w komentarzach, za każdym razem, gdy trafisz w szufladę, musi on mieć reset swój stos drogi nawigacyjnej, który ma tę trasę jako punkt początkowy, a następnie możesz zacząć pchać i strzelać.

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

Jako inny marginesie, widzę, że na podstawie własnych potrzeb, będzie to prawdopodobnie dobry pomysł, aby spróbować użyć react-native-router-flux ponieważ będzie w stanie określić swój routes, sub-routes, integrate with react-native-drawer i integrate with Redux.

+0

Przepraszam, ale czy mógłbyś wyjaśnić na swoim pytaniu i pokazać, co masz na myśli, mówiąc, że funkcja 'connect' nie odwzorowuje' dispatch' z podanym przeze mnie kodem? –

+0

Jak wymyśliłeś: '{ pushRoute: (trasa) => push (trasa), popRoute:() => pop(), }'? z dokumentacji "react-redux"? Ma być podpisem funkcji. – rclai

+0

https://medium.com/@dabit3/react-native-navigator-experimental-part-2-implementing-redux-c6acbf66eca1#.trrcjkhju stąd –