Creating Dedicated Stylesheets for Authentication Components
Now that we have our two inputs implemented correctly, so we have a password field and we have an email field, now it's time for us to perform a small refactor.
Guide Tasks
  • Read Tutorial
  • Watch Guide Video
Video locked
This video is viewable to users with a Bottega Bootcamp license

So let's take a look at this and I don't just wanna tell you what to do here, I also wanna walk through what to look for because when you start building out your own applications, I want your mind to continually be thinking about looking at the code and then picking up these little hints so that you can know exactly how to build out your own apps and how to write them in a way that they're gonna be able to scale properly and they're gonna be easy for yourself and your other team members to maintain.

When I look at this code right here, it all works which is good. But we can do better 'cause look at this, look at some of this code here. We have the View tag has the exact same styles on the top and the bottom. That already is a little bit of a hint that we could refactor that. Anytime you see duplicate code, usually that means that you can create some type of function or some kind of shared resource so that everything else in the app can use it.

So the View tag is already giving me one little hint, but then when we come down in the TextInput, this is really something that can be refactored. As you can see right here, we have the identical backgroundColor, borderRadius, height and paddingLeft for both our email and our password fields.

What this is telling me is we can now go and create a dedicated style sheet file that all of this code can use. One, it's gonna make this entire code file a lot easier to read because you're not gonna have all of this extra style information inside of it. But then also, any other part of the application that ever needs to use this type of style where you have this rounded text box and you're using the same type of look and feel, that other component is also gonna be able to use it. So in this guide, that's what we're gonna do.

I wanna open up the styles here on the left-hand side. So if you navigate down in the app and go to styles, you can see right now all we have is navigation,

large

I'm gonna create another style here. I'm gonna create New File, and let me just say auth and then, or you know what I'm gonna do here that I like even better, I like to wrap up these types of helper modules inside of really what the goal is what they accomplish, in this case, they accomplish some type of form, in this case it's our authentication form.

I'm gonna create a module here called forms and then let's just say text inputs because that's exactly what we're using. So I'm gonna say forms/textInputStyles and then that's gonna be just a regular .ts file. Now you can see we have this new module inside of our styles directory called forms and it's called textInputStyles.

large

Now we can reference what we used in navigation here to remember our inputs. Remember we need a StyleSheet input and then if we're gonna use any colors, we can use the colors. So I'm just going to copy all of this from our bottomTabStyles file and I'm gonna paste it in and then I'm gonna get rid of all of this content inside of it.

textInputStyles.ts

import { StyleSheet } from "react-native";
import { dark } from "../colors";

export default StyleSheet.create({

});

So let's close that and now let's go back to our AuthScreen and see what we can create or what we can pull out. So first and foremost, we have these View tags. I think this is a great name for this would be something like a textFieldWrapper 'cause that's exactly what it does.

So let's go and let's grab all of this code here, I'm gonna pull it out and in textInputStyles I'm gonna create something called textFieldWrapper and it's gonna be an object and I'm just gonna paste in those styles that we pulled out. And then I'm also gonna put them on different lines just so it's a little bit easier to see. So that's the first one.

textInputStyles.ts

import { StyleSheet } from "react-native";
import { dark } from "../colors";

export default StyleSheet.create({
  textFieldWrappler: {
    marginTop: 20,
    marginBottom: 20
  }
});

Now the next one was the actual text input itself, so let me I'm gonna hit Save here and prettier is gonna give me a little update on the way I'm doing indentation. And now let's come down here and let's grab the styles, all the styles from our TextInput. So I'm going to copy all of this or I'll just cut it out and in textInputStyles here, I'm just gonna call this a textField.

You can call these whatever you like, oh and I actually grabed both sets of the curly brackets as you can see. You can call it whatever you like but I like this to be very descriptive and so the better you describe it, the easier you're gonna be able to read it later on.

textInputStyles.ts

import { StyleSheet } from "react-native";
import { dark } from "../colors";

export default StyleSheet.create({
  textFieldWrappler: {
    marginTop: 20,
    marginBottom: 20
  },
  textField: {
    backgroundColor: "white",
    borderRadius: 20,
    paddingLeft: 20
  }
});

So now we have those two styles, so let's go and let's actually bring them in and make sure all of this is working. So I'm gonna come all the way up to the top of the file and we're gonna import this set of styles. So I'm gonna say import textInputStyles from and inside of here we're gonna go back back, oh and you know what? One little hint and I'm glad that you're seeing this because this can be a little bit confusing.

If you're using some type of import auto complete extension like I am, and I'll show you which one it is if you're interested, I have this Auto Import extension that's very handy in VS Code.

large

You can click on it and you can see that that's what it is.

large

This works great except if you have errors on the page. So if you have errors on the page, then it's not always gonna work 'cause notice, when I say dot dot here, right away it wasn't giving us access to that file system.

large

So that part is a little bit buggy, so if that ever happens or you find that, let me show you how to fix it. Come down here to the file itself and the reason it's giving you these errors is because we have these empty style brackets. We can just fix that by just putting in an empty object and now we don't have any errors there.

large

So now let's say import textInputStyles from and then dot dot slash dot dot slash and let's go into our styles directory, into our new fancy forms directory and then we want to import textInputStyles and you can see now it's working.

AuthScreen.tsx

import textInputStyles from "../../styles/forms/textInputStyles";

So just a little hint if you ever run into a situation where it's not showing you the recommended files, that can be really confusing and also if you have a very large project, it can be very buggy. So just make sure you fix any typescript errors on the page and that will start working for you.

So I'm going to grab these textInputStyles and now I can come down and let's go and let's get rid of all of this code inside that View tag and when I say dot this actually gives me the recommendation because we're using typescript, it tells me the different object items I have inside which I have that textFieldWrapper and the textField.

large

So I'm gonna use a textFieldWrapper first and now down here, I'm gonna get rid of all of these styles and say textInputStyles dot and this is our textField. Coming down, we're gonna do the exact same thing and you can just copy these or you can type 'em in. So textInputStyles, textFieldWrapper and then for our style, we're gonna say textInputStyles.textField.

AuthScreen.tsx

return (
  <View style={authScreenStyles.container}>
    <Text style={{ color: "white" }}>{headerText()}</Text>

    <View style={textFieldWrapper}>
      <TextInput
        placeholder="Email"
        value={email}
        onChangeText={val => setEmail(val)}
        style={textField}
        autoCapitalize="none"
        spellCheck={false}
      />
    </View>

    <View style={textFieldWrapper}>
      <TextInput
        placeholder="Password"
        value={password}
        onChangeText={val => setPassword(val)}
        style={textField}
        secureTextEntry={true}
      />
    </View>

Now let's hit Save, and as you can see over here and you can also manually hit refresh too, this is all working. All of our styles have been brought in properly.

large

So that is working very nicely and I'm happy with that. One other thing I wanna do is let's come up all the way till the top here and you can see we have quite a few styles up here for our container. I'm not a big fan of having all of this hardcoded in because say we wanna create another container that looks very similar to this and we are gonna be doing that throughout the course.

So this one's gonna be kind of specific to our authStyles so I'm just gonna create a dedicated module for styles that are specific to a screen or to a category or a stack. So let's open up the file system one more time here and go down to our styles directory and I'm gonna now create, I'm gonna go New File and here I'm gonna say screens.

You could also, another thing that I've done for other applications, I might say something like stacks because then I could say stacks and then I could say auth because this is gonna be specific to our auth stack and then I could say something like authScreenStyles. It's completely up to you on how you personally wanna organize these. I'll do it this way just because if I were building out a larger application, this is probably the structure that I'd follow.

Code Tree

styles > stacks > auth > authScreenStyles.ts

large

So we've created that now, I've verified that this is nested directly under the stacks and that's inside of styles and once again, just to make it easy on us for the imports, I'm just gonna copy everything here, paste it in and in this case I actually do want to get the container.

I'm not gonna use the colors yet but I do want to name this container and that's one of the nice things about whenever you are creating these dedicated style sheets, you can reuse some of the same names. They're not gonna override the same way they would if you were writing in say pure Sass or CSS because, remember, we don't have that same cascading nature of the style sheets. These are simply objects and data that you can call from any place in the application.

So I'm gonna call this container and inside of here let's add a background color. So I'm gonna say background color and because I use auto import, I can just start typing out dark, hit Tab and it's going to import that for me.

authScreenStyles.ts

export default StyleSheet.create({
  container: {
    backgroundColor:dark
  }
});

So obviously you could do all of that manually but that's part of the reason why I love that extension and I will put it down in the show notes, so that you can add it to your own Visual Studio Code package if you would like 'cause I will tell you that saves me a ton of time when I'm writing code.

So background color, let's add some padding. I'm gonna go with padding 15. Let's add a height of 100% and then lastly let's just add some marginTop and for this I'll just go with, let's just say 100. We're gonna change this later on but for right now that will give us what we need.

authScreenStyles.ts

export default StyleSheet.create({
  container: {
    backgroundColor:dark,
    padding: 15,
    height: "100%",
    marginTop: 100
  }
});

So I'm gonna hit Save and now if I go back to our AuthScreen, I'm gonna go import one other set of styles. So import authScreenStyles from and then let's go ../../styles, now we're gonna go into stacks into our auth stack and then into our authScreenStyles.

AuthScreen.tsx

../../styles/stacks/auth/authScreenStyles

From here, I'm just going to copy this, come back down and instead of having our style tag here or View tag using all of these inline styles, now let's just replace it with authScreenStyles.container.

AuthScreen.tsx

return (
  <View
    style={authScreenStyles.container}
  >

So now if I hit Save, you can see that looks a lot better.

large

The reason why it looks slightly different is because before we weren't using padding and now we have padding right here on the sides.

So I'm really happy with how all of this is coming along. I think this component looks a lot better, has more reusable code that now we can use in other parts of the application. There's only one other thing that I would like to do and to show you is a refactor but don't worry, it's pretty quick. I know this video is going on a little longer but this one is a really fun one.

So notice how we have our textInputStyles here, we have this import. And down below we're calling textInputStyles multiple times. In fact we're calling it four times here. We can actually streamline this code a little bit as well by using what is called destructuring.

So the way that we can do this is if I come all the way up here, I can actually extract out those objects and this is not something specific to React, to React Native, anything like this, this is pure JavaScript and you are gonna see this a lot inside of other tutorials and documentations. So I'm gonna be doing that quite a bit in this course.

One, because this is a more advanced course and so I wanna teach you those kinds of things but also, so that when you look at documentation and you see destructuring, it's not gonna take you off guard. So the way you can do destructuring is inside const and then inside of curly brackets list out the objects, the keys that you want to pull out of the object.

So we know the names of these two keys, one is textFieldWrapper, so I'm just going to pull out the textFieldWrapper. And then the other one is textInput or textField. And that's the reason why I copied them because I've done that plenty of times where I think the class name was something else and turned out to be wrong, so copy those two in.

Now the way you can do destructuring is by saying equals textInputStyles.

AuthScreen.tsx

const {textFieldWrapper, textField} = textInputStyles;

So the way this works and you can write this in pure JavaScript and so you could open up a browser and test this out on just a normal object. That's one of the cool things about the way that React Native uses the styleSheet component is it converts all of it into styles that the React Native code can use inside of the device but also it gets treated like a regular object. And so these are simply keys in the object.

Now what we can do because we've extracted those is we can come down here and we can get rid of that first call because now we've extracted those out. So now I can get rid of that, our textField, now hit Save. And you can see that that is working nicely, everything's exactly the same.

large

Now my rule of thumb for when to use destructuring is if I have really two or more elements that I'm pulling out of an object, then I will use it because I don't wanna have all of this kind of code where I say something styles dot and then whatever the name is, I don't wanna have those scattered throughout the entire application. So what I like to do is in cases like this where I only have a single time that I'm calling that element, it's fine, I just call it and I'm not gonna perform destructuring.

But in cases where I have something that's called, in this case, like four times, then I personally like to perform destructuring. And one last review on that, the way it works is you say const just like a normal variable and then from there you write curly brackets and that's where you list out each one of the keys.

So in doing that, you just have to look at whatever the object is and then you can just say okay, so I'm using the textFieldWrapper and the textField, those are my two key names and then I can just come and I can pull them out from that object.

Now this does not work, just in case you're curious about this, this would not work if you just put those brackets around here. So in order for this to work, you fist have to create the object which is what happens when you import it and then you can go and you can perform the destructuring.

One last thing, just because we're not using this dark variable inside of textInputStyles, just get rid of that just so we don't have any unused or it's called orphan code hanging around in our application.

textInputStyles.ts

import { StyleSheet } from "react-native";

export default StyleSheet.create({
  textFieldWrapper: {
    marginTop: 20,
    marginBottom: 20
  },
  textField: {
    backgroundColor: "white",
    borderRadius: 20,
    height: 40,
    paddingLeft: 20
  }
});

So great job if you did that. To review, we created our own dedicated set of style modules, we're able to implement those into our AuthScreen component and then we also performed destructuring to make our code a little bit more readable.

Resources