Alexey Ukolov
Alexey Ukolov

Reputation: 651

How to choose starting screen of react-native app based on redux state?

There are several screens in my react-native app that user should go through sequentially: first they should login, then set pin code for the app, then select a city and only then can they use main functionality. On the next start user should go straight to the Main screen.

I'm managing state with redux and keep data in async storage on device. When the app starts data is loaded from storage and based on it user should be sent to some screen or other.

The question is: how can I do this, when and where in the app lifecycle?

Let's look at this example: https://github.com/react-community/react-navigation/tree/master/examples/ReduxExample.
It generates initial navigation state, but does so statically:

// Start with two routes: The Main screen, with the Login screen on top.
const firstAction = AppNavigator.router.getActionForPathAndParams('Main');
const tempNavState = AppNavigator.router.getStateForAction(firstAction);
const secondAction = AppNavigator.router.getActionForPathAndParams('Login');
const initialNavState = AppNavigator.router.getStateForAction(
  secondAction,
  tempNavState
);

What should I change in that example if I want to load isLoggedIn flag from device storage and navigate user accordingly?

Upvotes: 0

Views: 2285

Answers (1)

Hernán Albertario
Hernán Albertario

Reputation: 930

I had the same issue some time ago, I will tell you how I solved it: In my first screen called App.js I put redux configuration:

const App = () => (
  <Provider store={store}>
    <View style={{ flex: 1 }}>
        <Main />
    </View>
  </Provider>
)

In Main.js:

class Main extends Component {
    constructor() {
        super();
        this.state = ({
            initial_data_fetched: false
        })
    }
    componentDidMount() {
        this.props.isUserAthenticated();
    }

    componentWillReceiveProps(next) {
        if (next.token !== '') {
            if (!this.state.initial_data_fetched) {
                this.props.loadUserData(next.token);
            }
            this.setState({ initial_data_fetched: true })
        }
    }

    render() {
        if (this.props.processing_auth) {
            return (<Spinner size="small" />)
        } else {
            return (<Router authenticated={this.props.authenticated}/>)
        }
    }
}

const mapStateToProps = ({ auth }) => {
    const { processing_auth, authenticated, token } = auth;
    return { processing_auth, authenticated, token };
};

export default connect(mapStateToProps, { isUserAthenticated})(Main);

Finally, with react-native-router-flux I choose if show the login component, or the initial component. That is my Router.js file:

const RouterComponent = ({ authenticated }) => {

return (
    <Router>
        <Overlay>
            <Stack key="root" hideNavBar>
                <Stack key="authentication" >
                    <Scene key="login"
                        component={LoginForm}
                        hideNavBar
                        initial={!authenticated} />
                </Stack>

                <Stack
                    back={false}
                    key="main"
                    initial={authenticated}
                    type={ActionConst.RESET}>

                    <Lightbox key="mainScreen">
                        <Scene
                            hideNavBar
                            key="mainScreen"
                            component={Parking}
                            initial={authenticated}
                        />

                </Stack>
            </Stack>
        </Overlay>
    </Router>
);
};

export default RouterComponent;

Hope it helps you!!

Upvotes: 3

Related Questions