0
votes

My routes are not triggering screen changes using the latest React Navigation v1.5.0.

I have integrated Redux in my setup as detailed in the react-navigation-redux docs. The biggest change I see here is the 'addListener' setup, although I'm not sure this is what is preventing the screen changes. My routes were working fine using v.1.0.

I see the navigation action being fired and the screen being added to the navigation state in the debugger, but the screen isn't changing.

Clicking on the button below dispatches the action, but the screen doesn't change to the About screen and stays on the Home screen.

RootNav

StackNavigator
  - Home
  - About

Index.js

const middleware = createReactNavigationReduxMiddleware(
  "root",
  state => state.navigationState,
)

const addListener = createReduxBoundAddListener("root");

class App extends Component {
  render () {
    return (
      <View>
        <RootNav navigation={addNavigationHelpers({
         dispatch: this.props.dispatch,
         state: this.props.navigationState,
         addListener,
         })} />
     </View>
    )
  }
}

BUTTON

<TouchableHighlight onPress={ () => 
   this.props.dispatch(NavigationActions.navigate({
     routeName: 'About'
   })) }>
  <Text>About</Text>
</TouchableHighlight>

STATE AFTER CLICKING BUTTON:

nav: {
  key: StackRouterRoot,
  index: 1,
  isTransitioning: true,
  routes: [
   0: {routeName: 'Home'},
   1: {routeName: 'About'},
  ],
}

How do you properly dispatch route/screen changes?

1

1 Answers

0
votes

Your navigation state is not bound to the redux, considering that you're using redux-navigation. You need to create a Navigation reducer and bind it to the store.

For eg

// Nav.js
// This is your exported router, which gets the initial State
import AppNavigator from '../Navigation/AppNavigation'
const initialState = AppNavigator.router.getStateForAction(AppNavigator.router.getActionForPathAndParams('LaunchScreen'))

export default reducer = (state = initialState, action) => {
  const newState = AppNavigator.router.getStateForAction(action, state)
  return newState || state
}

and bind it to your store like this

// Store.js
    const RootReducer = combineReducers(config, {
  nav: Nav,
  // ...other reducers
});

and finally use it in your Redux Navigation state as

function ReduxNavigation (props) {
  const addListener = createReduxBoundAddListener('root')
  const { dispatch, nav } = props
  const navigation = ReactNavigation.addNavigationHelpers({
    dispatch,
    state: nav, // this is bound to redux store using mapStateToProps
    addListener
  })

  return <AppNavigation navigation={navigation} />
}

const mapStateToProps = state => ({ nav: state.nav })
export default connect(mapStateToProps)(ReduxNavigation)

as mentioned in the docs