React Native Firebase Chat with Expo – Part II

In Part I, we went over the set up for the chat app. Here’s where we’ll get the fun coding part. The first thing we want to do is set up some screens. We want to be able to navigate between them, and add some simple styling.

Directory set up

First, check out the v2.0 tag from the github repository. You can fetch and list them first, and create a new branch for this Part II code. In case you need it, here’s the repo link again.

git fetch --all --tags
git tag
git checkout tags/v2.0 -b <branch>

We’ll keep all of our code in a new src directory with a screens and components subdirectory. Before we fire up the app again, let’s make sure to install some new Node packages we’ll need in the next steps.

expo install react-navigation-stack react-navigation-drawer react-native-elements

These packages will provide navigation and fancier native elements than the ones that come with React Native. If you’re not using native elements yet, you’ll soon be a big fan.

Go ahead and fire up the app.

expo start -c

If all goes well, you should see a big white screen with the text “Home Screen” at the top. If you run into any errors, read them. You most likely didn’t install a Node package or they may have changed names since this article was posted. In most cases, the errors give you exactly what you need to work out any issues.

Understanding navigation

Since this series is mainly focused on a few React Native and Firebase concepts, I won’t have the bandwidth to cover all the code in the app. I’d encourage you to start Googling or as questions if you come across something unfamiliar.

The App.js is fairly simple, it’s basically making use of the React Native Elements ThemeProvider to set the styles for the entire app. It also sets up the DrawerNavigator for a Settings screen that will pop under the Home Screen. A StackNavigator will handle the sign in/sign up flow.

const switchNavigator = createSwitchNavigator({
    mainFlow: createDrawerNavigator(
        {
            Home: {
                screen: HomeScreen
            },
            Settings: {
                screen: SettingsScreen
            }
        },
        {
            initialRouteName: "Home"
        }
    ),
    loginFlow: createStackNavigator(
        {
            Signup: { screen: SignUpScreen },
            Login: {
                screen: LoginScreen
            }
        },
        {
            initialRouteName: "Login"
        }
    )
});

const App = createAppContainer(switchNavigator);

export default () => {
    return (
        <ThemeProvider theme={theme}>
            <App
                style={{ backgroundColor: "white" }}
                ref={navigator => {
                    setNavigator(navigator);
                }}
            />
        </ThemeProvider>
    );
};

The navigation part is pretty simple. We set up the loginFlow and mainFlow. After we flesh out more code, we’ll always make sure a user is logged into Firebase. If not, they’re taken to the loginFlow. If they have an account and log in, we’ll persist the login using AsyncStorage and navigate them to the mainFlow instead.

Theme styling basics

export default () => {
    return (
        <ThemeProvider theme={theme}>
            <App
                style={{ backgroundColor: "white" }}
                ref={navigator => {
                    setNavigator(navigator);
                }}
            />
        </ThemeProvider>
    );
};

You’ll notice the ThemeProvider JSX from React Native Elements above. This is completely awesome and allows us to set the styling for the app in one place and use them everywhere. Before the navigation code, I’ve created a simple theme with the following styles.

const offset = 16;

const theme = {
    Button: {
        fontSize: 42,
        raised: false,
        buttonStyle: {
            backgroundColor: "#8ec43e",
            margin: offset
        }
    },
    messageFormStyle: {
        backgroundColor: "#FFF",
        flex: 1,
        justifyContent: "flex-end",
        marginBottom: 36
    },
    viewStyle: {
        backgroundColor: "#FFF"
    },
    FlatList: {
        marginLeft: offset,
        marginRight: offset
    },
    ListItem: {
        marginRight: offset
    },
    colors: {
        primary: "#023467",
        secondary: "#8ec43e"
    },
    containerStyle: {
        flex: 1,
        flexDirection: "column"
    },
    Input: {
        leftIconContainerStyle: {
            marginRight: 5
        },
        leftIcon: {
            color: "#555",
            fontSize: 12
        },
        inputStyle: {
            height: 65
        },
        marginLeft: 10,
        fontSize: 16
    },
    title: {
        marginTop: offset,
        marginLeft: offset,
        fontSize: 16
    },
    h4: {
        marginTop: 16,
        marginLeft: 16
    },
    logoContainer: {
        justifyContent: "center",
        alignItems: "center",
        backgroundColor: "white",
        paddingTop: 10
    },
    logo: {
        paddingTop: 100,
        width: 150,
        height: 88
    },
    title: {
        marginTop: offset,
        marginLeft: offset,
        fontSize: offset
    },
    errorMessageStyle: {
        color: "red"
    }
};

Styles in React Native Elements use camel case, but are mostly self explanatory. You can read more about theme customization in their documentation. As we start to flesh out the rest of the app and its components, we’ll simply be making use of the ThemeContext to refer to this initial object’s styles. For an example, take a look at the HomeScreen’s h4 text component.

import { ThemeContext, Text } from "react-native-elements";

const HomeScreen = ({ navigation }) => {
    const { theme } = useContext(ThemeContext);

    return (
        <View style={theme.viewStyle}>
            <Text h4 style={theme.h4}>
                Home Screen
            </Text>
        </View>
    );
};

To change all h4 Text elements to be red throughout the app, all we need to do is tweak the h4 style on the theme object of the App.js.

h4: {
        marginTop: 16,
        marginLeft: 16,
        color: "red"
    },

If you’re running the app in a simulator or your device, add the color and save App.js. Watchman should kick in and auto refresh your app with a hideous red h4 tag that says Home Screen.

Three steps to using themes

Going forward, to use any style throughout the app, a component needs three steps. Using these steps, you can keep your app’s styling consistent and only ever need to change one individual style.

  1. Import useContext and ThemeContext into your component
  2. Declare your theme object with useContext
  3. Use a named style from your theme on any component
// 1.
import { useContext } from "react";
import { ThemeContext, Text } from "react-native-elements";

// 2.
const { theme } = useContext(ThemeContext);

// 3.
<Text h4 style={theme.h4}>Home Screen</Text> 


Theme mastery!

That’s basically theme customization with React Native Elements in a nutshell. No more creating style objects on each and every screen or component. Using the ThemeContext, you can easily and consistently style your entire app. Save yourself and your fellow developers from many headaches.

At this point, you’re basically a Theme master. Well you have to create 9,999 more themes before you become a master at it. But you’re well on your way! We made use of React’s ThemeContext hook to be able to use plain JavaScript objects and avoid class-based components. That makes the code much simpler, cleaner, and easier to understand.

Even though its a simple app, there’s a lot to it. So in Part III, we’ll get into hooking up Firebase and navigating between screens. For now, revel in your theme mastery, tell your dev friends. Start removing all those const styles in every component and screen of your other apps.

Facebooktwitterlinkedin