2
votes

need some help here, i having some problem when using redux with react navigation.

Whenever i update state in redux, the react-navigation will reset to initialRouteName in my DrawerNavigator which is Home

How can i stay on that screen after this.props.dispatch to update Redux state?

Is there any step that i should do when integrate redux with react-navigation?

Thank you so much for any help. Appreciate it

App.js

This is where i declare my StackNavigator, my DrawerNavigator is nested in StackNavigator

import React, { Component } from "react";
import { connect, Provider } from "react-redux";
import { Platform, BackHandler, View, Text } from "react-native";
import { Root, StyleProvider, StatusBar } from "native-base";
import { StackNavigator, NavigationActions } from "react-navigation";

import Drawer from "./Drawer";
import AuthNavigator from "./components/login/authNavigator";

import Home from "./components/home";
import Settings from "./components/settings";
import UserProfile from "./components/userProfile";

import getTheme from "../native-base-theme/components";


const AppNavigator = token => {
    return StackNavigator(
        {
            Drawer: { screen: Drawer },
            Login: { screen: Login },
            Home: { screen: Home },
            AuthNavigator: { screen: AuthNavigator },
            UserProfile: { screen: UserProfile }
        },
        {
            initialRouteName: token ? "Drawer" : "AuthNavigator",
            stateName: "MainNav",
            headerMode: "none"
        }
    );
};

class App extends Component {
    constructor(props) {
        super(props);

        this.state = {
            isReady: false
        };
    }

    componentDidMount() {
        setTimeout(() => {
            this.setState({ isReady: true });
        }, 500);
    }

    render() {
        let token = null;
        const users = this.props.auth.users;
        const index = this.props.auth.defaultUserIndex;
        if (users.length > 0) {
            token = users[index].token;
        }
        const Layout = AppNavigator(token);
        return (
            <Root>
                <StyleProvider style={getTheme()}>{this.state.isReady ? <Layout /> : <View />}</StyleProvider>
            </Root>
        );
    }
}

var mapStateToProps = state => {
    return {
        auth: state.auth
    };
};

module.exports = connect(mapStateToProps)(App);

Drawer.js

This is my Drawer, whenever i update Redux state, the app will pop back to the initialRouteName of DrawerNavigator which is Home

import React from "react";
import { DrawerNavigator, StackNavigator } from "react-navigation";
import { Dimensions } from "react-native";
import SideBar from "./components/sidebar";

import Home from "./components/home/";
import Settings from "./components/settings/";

const deviceHeight = Dimensions.get("window").height;
const deviceWidth = Dimensions.get("window").width;

const Drawer = DrawerNavigator(
    {
        Home: { screen: Home },
        Settings: { screen: Settings },
        CompanyProfile: { screen: CompanyProfile }
    },
    {
        initialRouteName: "Home",
        contentOptions: {
            activeTintColor: "#e91e63"
        },
        contentComponent: props => <SideBar {...props} />,
        drawerWidth: deviceWidth - 100
    }
);

export default Drawer;

Reducer.js

const defaultState = {
    users: [],
    defaultUserIndex: 0
};

const defaultUserState = {
    phoneNumber: undefined,
    email: undefined,
    name: undefined,
    userId: undefined,
    token: undefined,
    avatar: undefined
};

module.exports = (state = defaultState, action) => {
    console.log("reducer state: ", state);
    switch (action.type) {
        case "AUTH_USER":
        case "UNAUTH_USER":
        case "UPDATE_AVATAR":
        case "UPDATE_PHONENUMBER":
        case "UPDATE_PERSONALDETAILS":
            return { ...state, users: user(state.defaultUserIndex, state.users, action) };

        case "CLEAR_STATE":
            return defaultState;
        default:
            return state;
    }
};

function user(defaultUserIndex, state = [], action) {
    const newState = [...state];
    switch (action.type) {
        case "AUTH_USER":
            return [
                ...state,
                {
                    phoneNumber: action.phoneNumber,
                    name: action.name,
                    email: action.email,
                    userId: action.userId,
                    token: action.token,
                    avatar: action.avatar,
                }
            ];

        case "UNAUTH_USER":
            return state.filter(item => item.token !== action.token);

        case "UPDATE_AVATAR":
            newState[defaultUserIndex].avatar = action.avatar;
            return newState;

        case "UPDATE_PERSONALDETAILS":
            newState[defaultUserIndex].name = action.name;
            newState[defaultUserIndex].email = action.email;
            return newState;
        default:
            return state;
    }
}
1

1 Answers

3
votes

In your case: you create new AppNavigator on each render invoke. And each of instance have new navigation state.

You can fix it by moving initialization to constructor, so every next render it will use same object.

constructor(props) {
    super(props);

    this.state = {
        isReady: false
    };
    const token = //sometihng
    this.navigator =  AppNavigator(token)
}

Also: explore examples of redux integration in official docs https://github.com/react-community/react-navigation/blob/master/docs/guides/Redux-Integration.md