
No Comments Yet
Be the first to share your thoughts and start the conversation.
Be the first to share your thoughts and start the conversation.
How did you manage to remove the blur property and reach here?
Upgrading gives you access to quizzes so you can test your knowledge, track progress, and improve your skills.
By logging in, you'll unlock full access to this and other free tutorials on JSM Pro.
Why? Logging in lets us personalize your learning experience, track your progress, and keep you in the loop with new workshops, coding tips, and platform updates.
You'll also be the first to know about upcoming launches, events, and exclusive discounts.
No spam—just helpful content to level up your skills.
If that sounds fair, go ahead and log in to continue →
Enter your name and email to get instant access
In this lesson, we dive into implementing authentication within an application using AppWrite. The process includes creating user accounts, linking them with a database, and managing UI components for user input during sign-in and sign-up. The steps detailed in the session cover everything from sketching out the data flow to crafting reusable components for the authentication screens.
00:00:02 Okay, so let's talk auth.
00:00:05 How would we go about implementing authentication within our application?
00:00:09 Might be better if I sketch it out.
00:00:12 So first things first, we start with the user entering their email and password.
00:00:18 So I'll just say user enters data.
00:00:22 Once they enter their email and password, we then want to call the AppWriteAuth function.
00:00:30 This function will then create a new auth user.
00:00:35 And after we create a new auth user, we then want to call the AppWrite database.
00:00:41 So I'll drag that here and just say call AppWriteDB.
00:00:48 We then want to store this new user information in the user collection in the database, which we can then easily connect with some other collections to
00:00:58 form relations.
00:00:59 Like we have a single user that can then be associated with a couple of different orders, for example.
00:01:06 So I have one order, two, three, and more, all associated with the same user.
00:01:12 Or maybe one user can add multiple addresses to their account.
00:01:16 So we have one and two.
00:01:19 we'll be able to easily create relations.
00:01:21 And this is useful for any kind of an e-commerce or food ordering application.
00:01:26 So for all of this to happen, we first have to create our database in AppRite.
00:01:31 So head over to your AppRite console under databases and create a new database, which we'll call app.
00:01:40 Within the app database, we need to copy its ID and then store it within our AppWrite config.
00:01:47 So back within our application, I'll head over to AppWrite TS, and right here below the platform, I'll add a database ID,
00:01:56 which will be equal to this ID we just copied.
00:01:59 After that, we want to go inside the database and create a new user collection.
00:02:05 So create collection and call it user.
00:02:09 Within it, we want to assign a couple of attributes.
00:02:12 So head over to attributes and create the first one.
00:02:15 It'll be a string that has a key of name with the size of 100, and we'll make it required.
00:02:24 That's one.
00:02:25 The second one will be email.
00:02:27 So choose email, type in email as the key, and make it required as well.
00:02:35 After that, we have the account ID.
00:02:37 So create a new variable of a type string and call it account ID with a size of 2200 should be enough and make it required as well.
00:02:50 After that, we want our user to have their avatar photo as well.
00:02:54 It'll be of a type URL, which you can call avatar, and make it required.
00:03:00 Now, you want to copy this user collection ID and put it within our config, just by saying user collection.
00:03:10 ID, and then paste what you just copied.
00:03:13 If you want to, you can also put these IDs within your environment variables like I've done for these ones, but we can do that together once we collect
00:03:21 all of them.
00:03:21 For now, you want to head over to your AuthLayout.
00:03:25 That is within the app, AuthLayout, and we want to develop the AuthScreenHeaderUI.
00:03:32 It is this one right here that is being shared across both the sign-in and the sign-up, which is exactly why I'll put it within the layout.
00:03:40 We can start by wrapping everything not within a safe area view, but within something called a keyboard avoiding view.
00:03:48 Looks like this, keyboard avoiding view coming from React Native.
00:03:52 And this component ensures that when a user is writing in any inputs, keyboard will appear below it automatically.
00:03:59 It won't go above the input field.
00:04:02 Also, when I was testing the app on Android, I noticed some weird behavior where we actually need to add some padding on iOS devices to push the content up,
00:04:11 and we have to add the height on Android devices.
00:04:14 So, how do we do some changes depending on the operating system?
00:04:19 Well, in this case, we can add a prop of behavior, which can be either padding or height.
00:04:26 And we can make it dynamic and say platform, which you import from react-native.os.
00:04:34 And this will give you access to the current operating system of your user's device.
00:04:39 If it is iOS, I'll apply padding.
00:04:43 Else, I'll apply a height.
00:04:45 Finally, within this keyboard avoiding view, we can render a scroll view.
00:04:51 This scroll view will have a class name equal to bgwhite and h-full, and it'll also have a special prop of keyboard should persist taps,
00:05:03 and it'll have a prop of handled.
00:05:06 Now, what does this mean?
00:05:07 Well, this prop ensures that tapping outside of the keyboard will dismiss the keyboard entirely, so that you can focus on clicking the Submit button,
00:05:15 for example.
00:05:16 Then we can have an additional view right within.
00:05:20 that'll have a class name of WFool and relative.
00:05:24 Now, we wanna apply different styles depending on the dimensions of the screen.
00:05:28 So I'll say style is equal to height, and we'll get access to the height of the screen in a similar way how we got access to the operating system.
00:05:37 You just say dimensions, which you import from React Native, and then .get, and here you can get the screen size, .height.
00:05:48 Once you get it, You want to divide it by 2.25. I found this number to work the best.
00:05:54 Later on, once we actually implement this screen, I'll show you what difference it'll make if we actually remove this height.
00:06:03 Finally, within it, let's render an image background coming from React Native, not Expo Image.
00:06:10 It'll be self-closing with a source of images.
00:06:15 coming from constants.login.graphic with a class name of size full and rounded-b-lg.
00:06:25 B stands for bottom.
00:06:27 With a resize mode equal to stretch.
00:06:31 So now we have this nice pizza image right at the top.
00:06:35 Then below this image background, I'll render yet another image, which will have a source.
00:06:43 equal to images.logo of our application with a class name of self-center, a size of 48, absolute positioning, minus bottom 16 to put it a bit below the image,
00:07:01 as well as a z-index of 10. So it appears over this image that we have.
00:07:07 And don't forget to import image from React Native.
00:07:11 Once you do that, you might need to reload just to make sure it's properly rendered.
00:07:14 And here it is.
00:07:16 Here you can put the logo of your fast food.
00:07:19 And now, before we go on to developing the UI of the sign-up and the sign-in screens, let's create two reusable components we'll need on this screen.
00:07:28 One is an input field and another is a button.
00:07:31 So, head over to components and create a new file, which will be called a custom input.tsx.
00:07:42 Run rnfe.
00:07:45 And there is our custom input.
00:07:47 And the other one will be a custom button.
00:07:49 So just create it in a same way.
00:07:54 RNFE, and now we have two of these components.
00:07:57 We can immediately try putting them on the actual layout for now, just so we can see them as we're developing them.
00:08:03 So if I head over into AuthLayout, right here within the scroll view, I will import the custom input, as well as the custom button components,
00:08:17 just so we can see them right here.
00:08:19 And now it's our turn to actually develop them.
00:08:22 So let me head over into the custom input first, and let me show you how we can make a reusable input component in React Native.
00:08:30 I'll start by making this input accept some props.
00:08:34 Things like a placeholder, which by default can say something like enter text.
00:08:41 Then we can accept the value of the input.
00:08:44 the onChangeTextHandler.
00:08:46 And I want to put all of these in a new line, just so it's easier to see.
00:08:50 So we have the placeholder.
00:08:52 the value, the unchanged text, and more, but I just wanted to properly indent it.
00:08:58 Then we also want to get the label of an input and a secure text entry ability by default set to false.
00:09:08 If this was set to true, then we would not be able to see what we're typing, and this is perfect for, you can guess it, passwords.
00:09:15 And finally, the keyboard type.
00:09:17 which will be default.
00:09:19 You can also change it to something like a number input if you want to.
00:09:23 Okay, so where are we going to get these props from?
00:09:27 Well, whenever you create a reusable component, you can pass some props to it wherever you're calling it.
00:09:32 And here, you can see that our custom input needs to accept some props.
00:09:36 It can already infer that we have some props right here, but it is always a good idea to specify a type.
00:09:43 For example, you can say this is of a type custom input props.
00:09:49 And then you could define a custom interface.
00:09:53 This is TypeScript related custom input props, where you would specify the type of each one of these properties.
00:09:59 like a placeholder could be string, onChange is a function, label will also be a string, and so on.
00:10:07 But just so we don't have to declare every single new type that we have here, you can create them right within a special file called type.d.ts.
00:10:18 which you can create in the root of your application, like the images.d.ts that I provided before.
00:10:24 So create it and call it type.d.ts.
00:10:29 You can then find it right here within the video kit, copy it and paste it here.
00:10:35 This will include a couple of interfaces that we're gonna use throughout the application, such as the custom input props interface that simply specifies
00:10:43 which types of props do we wanna pass.
00:10:47 And then you can just say custom input props, and it'll automatically be able to infer it from that type declaration file.
00:10:55 But now getting back to where we actually pass those props, you pass them whenever you call this component.
00:11:02 In this case, we're calling it right here within our layout.
00:11:06 So let's for a second imagine that we're using it within our sign in or sign up pages.
00:11:13 Maybe this can be, let's say sign in.
00:11:17 You'll need to pass a placeholder, something like enter your email.
00:11:23 Then you can also pass a value, which we'll have to get from the form.
00:11:27 So for now, I'll just make it an empty string.
00:11:30 An onChangeText, which will be a function.
00:11:34 We also have to pass the label equal to email.
00:11:38 And finally, a keyboard type, which in this case could be email address.
00:11:44 Yep, there's a special type for that too.
00:11:47 And now you can see that this component is getting what it deserves.
00:11:50 It's no longer complaining because it knows which props does it need.
00:11:55 And here I have a typo, secure text entry.
00:11:58 Perfect.
00:11:59 But now it's complaining that we're not actually using these props or parameters within the component.
00:12:05 So let's put them to use.
00:12:07 First things first, I want to wrap everything in a view that'll have a class name equal to WFool, so it takes the full width of the screen.
00:12:16 Then we can have a label, so that's going to be just a text with a class name of label.
00:12:22 And it'll dynamically render the label prop that we're passing into it.
00:12:26 In this case, it'll say email.
00:12:29 Then we can create a text input.
00:12:33 And this is a component which we can import from React Native.
00:12:37 It is a self-closing component and it has a lot of interesting props that we can pass into it, such as the auto capitalize,
00:12:45 which for now we can set to none because emails are not capitalized.
00:12:50 Whereas maybe if you had a name field, you could auto capitalize it.
00:12:55 Maybe autocorrect, which in this case, we want to turn to false.
00:12:59 A value, which will be equal to the value we're passing from props.
00:13:03 Same thing for the unchanged text.
00:13:05 Oh, this was supposed to be autocorrect.
00:13:08 Thank you for letting me know, Tabscript.
00:13:10 And then we have secure text entry, keyboard type.
00:13:14 All of these were passing directly from props.
00:13:16 We could also create the new useState hook, and we can call it isFocused.
00:13:21 And this will track the focused or unfocused state of the input.
00:13:26 Are we currently trying to type within it or not?
00:13:29 Don't forget to import useState from React.
00:13:33 Then, once we focus on this element, we can turn the Set Is Focused state to true.
00:13:41 But once we blur out of it, once we exit it, we can set it to false.
00:13:46 We can also pass it a placeholder, equal to placeholder coming from props, as well as a placeholder text color, which we can set to hash 888, which is
00:13:57 a dark version.
00:13:58 Finally, let's give it some class names.
00:14:01 I'll use this CN functionality from CLSX to always give it a class name of input.
00:14:08 But then only if it is focused, I'll also give it a border dash primary.
00:14:14 And else I'll give it a border gray 300. So that way we'll know whether it's focused and check it out.
00:14:21 You have an input on your screen and it has a nice border if it's focused, but for now it looks like we just jump out of the screen and can't see it.
00:14:28 Still, we have just implemented your custom input, which later on will not jump us out of the screen.
00:14:35 So very quickly, let's do a similar thing for the button.
00:14:39 We want this button to also accept some props.
00:14:42 So let's get them right here.
00:14:43 For example, an on.
00:14:45 Press.
00:14:46 We can also get a title, which by default can say something like, click me.
00:14:51 We can pass an additional style, a text style, a left icon if it has it, and the loading state for that button at the start set to false.
00:15:02 And we can attach a custom state to it.
00:15:05 Not custom input props, but custom button props.
00:15:09 So we know what we have to pass to it.
00:15:10 Now let's turn it from a view into a touchable opacity.
00:15:15 With a class name of CN, it'll always have a custom BTN.
00:15:22 And we can also pass some additional styles to it.
00:15:26 OnPress, we'll call the onPress function that we pass through props.
00:15:31 And there you have it, your custom button is already there.
00:15:33 Still, let's style it up a bit more for different use cases.
00:15:37 If it has a left icon, I'll also render that icon right here.
00:15:41 And then we will render a view.
00:15:45 This view will have a class name equal to flex-center and flex-row.
00:15:53 And within it, if we are currently loading, then I'll display a new component which we haven't used before, which is the activity indicator.
00:16:02 Make sure to import it from React Native.
00:16:05 Give it a size of small and a color of white.
00:16:11 But then if we're not loading, we want to show the actual text.
00:16:15 So I'll render a text element right here.
00:16:19 Remove this one that we had before.
00:16:21 And this one will have a class name of CN.
00:16:24 We'll always give it text white 100, paragraph semi-bold, but then we're going to also attach some dynamic styles, such as these ones,
00:16:36 which are coming directly from the props.
00:16:38 Text style.
00:16:40 There we go.
00:16:41 And now this button is not saying anything, so let's make it render the title that we're passing into it through props, which by default is set to click me.
00:16:50 And now that we have those two components, let's jump right into the sign-in and let's put them to use.
00:16:56 I'll first give this view a class name of gap of 10, bg of white, rounded-lg, padding of 5, and margin top of 5 to structure these elements a bit more nicely.
00:17:09 I'll also hit it within the layout and copy this custom input and custom button.
00:17:14 Remove it from here and then add it over to this sign in, but I'll leave it at the bottom for now because we want to use it later on.
00:17:23 Oh, but wait, when I paste them here, why aren't they actually showing up on the screen?
00:17:28 Did I forgot to add a slot to this scroll view?
00:17:32 No, the slot is here, but it actually should have been within the scroll view, not outside of it.
00:17:39 There we go.
00:17:40 So now we can see the sign in and you can see everything.
00:17:44 So now I'll head back to the sign in and let's actually implement it.
00:17:47 Directly within this view, we no longer need this text or a button.
00:17:51 We're going to start right off with a custom input that we have.
00:17:56 This will be the email input.
00:17:57 And then I want to duplicate it one more time below.
00:18:00 This time, it'll be for our password.
00:18:03 So I'll say, enter your password with a label of password.
00:18:08 And I won't have the keyboard type, but I'll have the secure text entry.
00:18:12 So whatever we're typing into the password actually gets hidden.
00:18:16 We'll test this part very soon as soon as we connect it with an actual form.
00:18:20 And then just below it, we want to render a custom button that'll have a title equal to sign in.
00:18:29 And we're good.
00:18:31 This looks like a proper valid sign in form.
00:18:34 But whenever you have sign in and sign up pages, you also want to create another view so we can switch between the two.
00:18:41 So I'll create another view that'll have a text with a class name of base-regular and text-gray-100.
00:18:51 And this one will say something like, don't have an account.
00:18:57 And then I'll create a link right below it.
00:19:01 That'll say, hey, sign up.
00:19:04 This link will then have an href pointing to the sign up page with a class name of base-bold and text-primary.
00:19:16 And of course, don't forget to import the link coming from Expo Router.
00:19:21 There we go.
00:19:22 Don't have an account?
00:19:23 Sign up.
00:19:24 And now we can switch between the pages.
00:19:26 We can also give this view a class name of flex, so they show one next to another, with justify center and a margin top of five,
00:19:36 flex row, and a gap of two in between the elements.
00:19:40 So this looks just a bit better now.
00:19:43 Perfect.
00:19:44 But now let's make it functional.
00:19:47 I'll create a new useState snippet right here at the top, and I'll call it isSubmitting.
00:19:54 This will be used for the loading states.
00:19:56 At the start, set to false.
00:19:58 And don't forget to import the useState hook itself from React.
00:20:03 I'll also create another useState, and this one I'll call form.
00:20:09 Set form, which by default will be set to an object with an empty email and an empty password.
00:20:17 Perfect.
00:20:18 Then I'll also create a new submit function.
00:20:22 const submit is equal to an asynchronous function where we want to check if form.email doesn't exist or if form.password doesn't exist.
00:20:38 That means that they haven't entered the data.
00:20:40 So we just want to render some kind of an alert, which with React Native, you can do easily just by saying alert.alert.
00:20:48 You can choose the type of the alert.
00:20:49 In this case, it'll be error, which is the title.
00:20:52 And then the message of the alert.
00:20:54 In this case, I'll say, please enter valid email address and password.
00:21:02 Perfect.
00:21:03 So later on, once we implement the sign up functionality, once you click the button, it'll give you an alert.
00:21:08 Then if these have been entered properly, we can start the submitting process.
00:21:14 So set is submitting to true.
00:21:16 And then we'll open up a try and catch block so we can properly authenticate our user.
00:21:22 Here we'll call the app right sign in function.
00:21:29 After that, we can maybe render another alert, dot alert, this time success, which we'll say user.
00:21:40 signed in successfully, and we'll just use the router.replace functionality to bring the user back to the homepage.
00:21:48 This router, of course, we have to import from expo router.
00:21:53 That is right here.
00:21:54 After that, if something goes wrong, so catch, we catch the error of an any type.
00:22:00 We'll also render another alert, rendering the error message.
00:22:04 And finally, whether it's exceeded or failed, we want to stop the submitting process.
00:22:10 So I'll set a submitting to false.
00:22:13 Perfect.
00:22:14 Now we can actually put these states to use right here within custom inputs.
00:22:20 For the first input, the value will be form.email.
00:22:25 Here is where we're storing the value of that email and onChangeText we'll be calling the setFormState.
00:22:34 Then you have to create a callback function because you're changing the state with the previous version of the state.
00:22:40 So I'll say prev and then you can create a new state object and automatically return it.
00:22:48 You do that by wrapping an object in parentheses.
00:22:52 We spread the previous state and we change the email to this new text that we collected from this input.
00:23:00 You can now also copy this value and on change and paste it for the second custom input, but this time it won't be the email,
00:23:09 it'll be the password.
00:23:10 And same thing here, we'll update the password.
00:23:14 Finally, once we click the custom button, We want to pass to it the isLoadingState, which will be equal to isSubmitting,
00:23:22 as well as what should happen once we press the button.
00:23:26 And what should happen is we should call the submit function.
00:23:31 Perfect.
00:23:31 So now if you click it, nothing really happens.
00:23:34 It just tries to go over to the homepage.
00:23:36 Now, it looks like something broke right here, so I'll try to reload my application, but it doesn't want to do it with the letter R,
00:23:43 so I'll stop the server from running, and then I will rerun mpx-expo-start-clear to just rebuild it.
00:23:50 and then I'll be able to reload it.
00:23:52 And if it still doesn't want to reload it, like is the case on my end, you can just close and reopen the ExpoGo app, and this will then re-bundle it.
00:24:01 Perfect.
00:24:02 Now, what are we going to do about the Sign Up page?
00:24:06 Thankfully, it's going to be more or less the same as the Sign In.
00:24:10 So just go ahead and copy this entire Sign In page, head over to Sign Up, and just paste it over.
00:24:18 Immediately, it'll start looking the same, but now we're going to make some changes.
00:24:23 First of all, I'll rename it to Sign Up.
00:24:26 right here, as well as here at the bottom.
00:24:30 Then the form on the sign up will have one additional field, and that'll be the name of our user.
00:24:37 So we'll add name right here.
00:24:40 At the start equal to an empty string.
00:24:42 Then we'll have the submit function where we also have to check for the name.
00:24:46 So I'll say if there is no form.name or these other fields, throw an error.
00:24:51 Here, we have to call the AppWriteSignUp function.
00:24:55 And then we have our inputs.
00:24:57 More or less, it's going to be the same, but we want to duplicate an additional one just above.
00:25:02 And this one will say, enter your full name.
00:25:07 It'll render the form.name and it'll modify the name within our state.
00:25:13 the label will be full name and we don't need the keyboard type.
00:25:17 Default is fine.
00:25:19 So now if you head over to sign up, you can see that now we have three different inputs.
00:25:24 The second two will remain the same as well as the button.
00:25:28 But we want to change some things right here.
00:25:30 Instead of saying don't have an account, I'll say already have an account.
00:25:36 If that is the case, well, go ahead and sign in.
00:25:42 So now we can switch between sign in and sign up.
00:25:46 Let's just make sure that this button says sign up as well.
00:25:51 So now check this out.
00:25:52 We have a fully functional UI layout built for two of these auth pages that share the same header, but their actual page details and the components within
00:26:03 them are different.
00:26:04 Here we're actually reusing very cleverly two different components to form two of these pages.
00:26:11 Now let's go ahead and test it a bit.
00:26:13 I took my phone in my hand and I'll start typing.
00:26:16 If I try typing something like Adrian, that works.
00:26:20 Then we can actually swipe down, see this to expand and be able to see other fields.
00:26:25 I'll enter my email.
00:26:27 Let's do it right here.
00:26:28 And then finally you can enter your password, which by default will be completely hidden.
00:26:36 Cool stuff, right?
00:26:38 But if you forget one of these fields and try to click sign up.
00:26:42 you'll see user signed in successfully.
00:26:44 Hmm, where is this coming from?
00:26:47 I'll search for signed in successfully.
00:26:51 And for sign up, we actually have to change it to say user signed up successfully.
00:26:56 And this should actually not be getting executed if we don't have access to these fields.
00:27:02 I think I might've forgotten to put a return here because if we return, then the rest of the function will not carry out.
00:27:09 And we have to also add it to sign in right here.
00:27:13 So now if you try to click on a sign in button, if you haven't yet entered your fields, you'll see, please enter valid email address and password.
00:27:24 And if you actually type something in, let's try to do something like this and a regular password.
00:27:32 You can see users signed in successfully and it tries to redirect you to home, but then we just automatically redirect back to sign in,
00:27:39 which means that everything is working.
00:27:42 This is amazing, right?
00:27:43 You've successfully implemented your first two auth screens.
00:27:48 In the next lesson, let's implement the auth functionality.