Skip to content

Instantly share code, notes, and snippets.

@NigelEarle
Created March 4, 2017 22:04
Show Gist options
  • Select an option

  • Save NigelEarle/1832bd7dbb2ea9e13aed932dec3618f7 to your computer and use it in GitHub Desktop.

Select an option

Save NigelEarle/1832bd7dbb2ea9e13aed932dec3618f7 to your computer and use it in GitHub Desktop.

Revisions

  1. NigelEarle created this gist Mar 4, 2017.
    181 changes: 181 additions & 0 deletions react-navigation-redux-ex.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,181 @@
    /**
    * @flow
    */

    import React from 'react';
    import {
    AppRegistry,
    AsyncStorage,
    Button,
    StyleSheet,
    Text,
    View,
    } from 'react-native';
    import {
    NavigationActions,
    addNavigationHelpers,
    StackNavigator,
    } from 'react-navigation';
    import {
    Provider,
    connect,
    } from 'react-redux';
    import {
    createStore,
    combineReducers,
    } from 'redux';
    import {
    persistStore,
    autoRehydrate,
    } from 'redux-persist';

    const ProfileScreen = ({ navigation }) => (
    <View style={styles.container}>
    <Text style={styles.welcome}>
    Profile Screen
    </Text>
    </View>
    );
    ProfileScreen.navigationOptions = {
    title: 'Profile',
    };

    const LoginScreen = ({ navigation }) => (
    <View style={styles.container}>
    <Text style={styles.welcome}>
    Screen A
    </Text>
    <Text style={styles.instructions}>
    This is great
    </Text>
    <Button
    onPress={() => navigation.dispatch({ type: 'Login' })}
    title="Log in"
    />
    </View>
    );
    LoginScreen.navigationOptions = {
    title: 'Log In',
    };


    const LoginStatusMessage = connect(state => ({
    isLoggedIn: state.auth.isLoggedIn,
    }))(({ isLoggedIn, dispatch }) => {
    if (!isLoggedIn) {
    return <Text>Please log in</Text>;
    }
    return (
    <View>
    <Text style={styles.welcome}>
    {'You are "logged in" right now'}
    </Text>
    <Button
    onPress={() => dispatch(NavigationActions.navigate({ routeName: 'Profile' }))}
    title="Profile"
    />
    </View>
    );
    });

    const AuthButton = connect(state => ({
    isLoggedIn: state.auth.isLoggedIn,
    }), dispatch => ({
    logout: () => dispatch({ type: 'Logout' }),
    login: () => dispatch(NavigationActions.navigate({ routeName: 'Login' })),
    }))(({ logout, login, isLoggedIn }) => (
    <Button
    title={isLoggedIn ? 'Log Out' : 'Log In'}
    onPress={isLoggedIn ? logout : login}
    />
    ));

    const MainScreen = () => (
    <View style={styles.container}>
    <LoginStatusMessage />
    <AuthButton />
    </View>
    );
    MainScreen.navigationOptions = {
    title: 'Home Screen',
    };

    const AppNavigator = StackNavigator({
    Login: { screen: LoginScreen },
    Main: { screen: MainScreen },
    Profile: { screen: ProfileScreen },
    });

    const AppWithNavigationState = connect(state => ({
    nav: state.nav,
    }))(({ dispatch, nav }) => (
    <AppNavigator navigation={addNavigationHelpers({ dispatch, state: nav })} />
    ));

    const initialNavState = {
    index: 1,
    routes: [
    { key: 'InitA', routeName: 'Main' },
    { key: 'InitB', routeName: 'Login' },
    ],
    };

    const initialAuthState = { isLoggedIn: false };

    const AppReducer = combineReducers({
    nav: (state = initialNavState, action) => {
    if (action.type === 'Login') {
    return AppNavigator.router.getStateForAction(NavigationActions.back(), state);
    }
    if (action.type === 'Logout') {
    return AppNavigator.router.getStateForAction(NavigationActions.navigate({ routeName: 'Login' }), state);
    }
    return AppNavigator.router.getStateForAction(action, state);
    },
    auth: (state = initialAuthState, action) => {
    if (action.type === 'Login') {
    return { ...state, isLoggedIn: true };
    }
    if (action.type === 'Logout') {
    return { ...state, isLoggedIn: false };
    }
    return state;
    },
    });

    class ReduxExampleApp extends React.Component {
    store = createStore(AppReducer, undefined, autoRehydrate());

    componentDidMount() {
    persistStore(this.store, { storage: AsyncStorage });
    }

    render() {
    return (
    <Provider store={this.store}>
    <AppWithNavigationState />
    </Provider>
    );
    }
    }

    const styles = StyleSheet.create({
    container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#F5FCFF',
    },
    welcome: {
    fontSize: 20,
    textAlign: 'center',
    margin: 10,
    },
    instructions: {
    textAlign: 'center',
    color: '#333333',
    marginBottom: 5,
    },
    });

    AppRegistry.registerComponent('ReduxExample', () => ReduxExampleApp);