
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.
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
This transcript contains no content, therefore it cannot provide any insights or themes.
00:00:02 Now that we've implemented authentication and integrated Sentry for monitoring, the next step is to implement the store functionality.
00:00:11 This will allow us to locally store the logged-in user information and access it throughout the entirety of the app, no matter where we are,
00:00:20 without needing to make additional requests to the server, in this case AppRite.
00:00:24 In React Native, store management can be handled using libraries like Zustand, Redux, or just React Context API.
00:00:32 They're all made to solve the same problem, maintaining the global state across the app.
00:00:38 And in this course, I'll teach you how to use Zustand.
00:00:42 Why?
00:00:42 Well, it's a great choice because it's lightweight, minimalistic, and has a very simple-to-understand API with zero boilerplate.
00:00:51 No reducers, action types, or a lot of that stuff that Redux just throws at you.
00:00:57 It's just plain JavaScript.
00:00:59 And unlike Context, it avoids re-render issues and is better for performance.
00:01:04 So, let's go ahead and simply install it by running npm install Zastand.
00:01:09 I'll do it within my second terminal.
00:01:12 and it should be installed within a second.
00:01:15 Then we can implement it by creating our first store.
00:01:19 Let me zoom this up for you so you can see it a bit better.
00:01:21 And a store in Zustand is nothing more than a simple hook.
00:01:25 You can put anything in it.
00:01:26 Primitives, objects, and functions.
00:01:29 And then the set function merges the state.
00:01:32 So let me copy this from the Zustand docs and create a new folder right here, which I will call store.
00:01:40 And within store we can create different types of stores.
00:01:43 So the first one I'll create will be called auth.store.ts.
00:01:49 And here I'll paste this new store that I just created.
00:01:53 And then the next step is to just use this store within your components.
00:01:57 You select what you want to get and you use it directly within your application.
00:02:02 It cannot be simpler than that.
00:02:04 And actually, that's it.
00:02:05 This is the end of the Getting Started page.
00:02:07 So, let me show you how we're gonna make it work with our use case.
00:02:11 First things first, I'll do an additional thing that is not required, but it'll help us with autocompletion and preventing bugs by ensuring consistency
00:02:20 of our types.
00:02:21 And that is to create...
00:02:23 that, a type, which I'll call authState, and I'll declare it as an object.
00:02:30 Now, this object will contain a couple of properties, like isAuthenticatedState, which will be of a type boolean.
00:02:38 It'll contain the actual user, which will be of a type user, coming from add forward slash type, or if we haven't yet created it,
00:02:49 it can be set to null.
00:02:51 Next, we're gonna have the loading state, so isLoading, which will be set to a boolean.
00:02:58 And then we can also have a couple of setter functions, like setIsAuthenticated, which will be a function that accepts a value of a type boolean.
00:03:11 Is the user authenticated?
00:03:13 Yes or no.
00:03:14 It says the state and returns nothing.
00:03:17 Avoid.
00:03:18 We can have one for setting the user, so I'll say set user, user of a type user or null, and then returns void.
00:03:26 Finally, we can have one for set loading, where it's going to accept the loading value of a type boolean.
00:03:33 And finally, we can have one that'll fetch the authenticated user, and this will be a function that will result in a promise.
00:03:41 So we can then extract the user from that promise.
00:03:44 Perfect.
00:03:45 So now that we have our AuthState, we know what we're working with.
00:03:49 So let's create our new store.
00:03:51 Instead of just calling it useStoreGeneric, I'll call it useAuthStore because it'll contain our authentication data, and that'll be equal to create a store
00:04:03 of a type of state, so we can pass it like this, and then we have a callback function where we can set and automatically return different values.
00:04:13 In this case, the values won't be Zestan's example of bears, it'll be what we set out to do.
00:04:20 The initial is authenticated state, which will be set to false.
00:04:26 We also have the user of a type null by default, isLoading, which will also be of a type true by default.
00:04:34 Now, you can see how everything is red, and that's because this is not matching the additional fields.
00:04:40 And TypeScript is really useful here because it's going to save our ass later on.
00:04:44 Next, we can also set the setter function for updating the isAuthenticated value to the store.
00:04:50 So we can say set isAuthenticated, which will be a callback function that accepts the value.
00:04:57 And then we use Zastan's setter to set it to be equal to an object with the isAuthenticated value set to whatever the value we pass in,
00:05:07 either true or false.
00:05:10 We can also do one for setting the user, which will be a function that accepts the user value.
00:05:16 and calls the setter and sets the user within an object.
00:05:20 We can do another one for setLoading and this one will also be a function that accepts a value and then ultimately just set calls the setter and then passes
00:05:33 the isLoading to the value that we want to pass.
00:05:36 And finally, we're missing the one where we want to fetch the authenticated user.
00:05:40 So I'll say fetchAuthenticatedUser will be equal to an asynchronous function, but this one will be just a tiny bit longer because we actually have to do
00:05:51 just that.
00:05:51 Well, fetch the user.
00:05:53 So I'll say setIsLoading to true because we want to start loading to fetch the user.
00:06:00 Then I'll open up a new try and catch block.
00:06:05 In the catch, I will consulog the error by saying fetchAuthenticatedUserError and then consulog the error itself.
00:06:14 And I will also set the isAuthenticated state to false because something went wrong, and I'll set the user to null.
00:06:23 And finally, I want to set the isLoading to false.
00:06:28 But if everything is going well, then we can try to fetch our authenticated user.
00:06:34 And we can do that by saying const user is equal to await get current user.
00:06:42 And this is a server action that we created within lib app, right?
00:06:46 If you remember, it is right here.
00:06:49 and then we can just check if we have successfully gotten back the user so if user exists then we can simply call the set method to set the isAuthenticatedState
00:07:01 to true and also to set this user to the state as user, so it has that proper type.
00:07:08 Else, we can simply set the state to be isAuthenticated, false, and user set to null.
00:07:17 Hopefully this makes sense.
00:07:18 So we're doing some extra work right now, but now we have access to this useAuth store, which we can call from absolutely any component or screen within
00:07:28 our application.
00:07:29 and any component at any point in time can get access to this state to determine whether a user is logged in or not.
00:07:38 Do you remember where we hardcoded that?
00:07:40 Well, it's going to be within app layout.tsx.
00:07:45 This is the general layout inside of which we're setting up Sentry as well as loading up some fonts.
00:07:51 For now, I will collapse this part, and we can focus on just fetching the state.
00:07:56 So right at the top, I will say const, And then these structure the isLoadingState alongside the fetchAuthenticatedUser.
00:08:07 And this will be equal to the hook that we have to export from the store.
00:08:11 So right below this useAuthStore in AuthStoreTS, don't forget to actually export default the AuthStore.
00:08:21 And then you'll be able to call it as a hook useAuthStore right here.
00:08:27 Once we get those two, you should be able to just add a new use effect below this use effect above.
00:08:35 And what you can do is just fetch the authenticated user.
00:08:39 Here, it's mentioning that the promise return from the fetch authenticated user is ignored, but that's totally okay because here we're not concerned about
00:08:47 this return.
00:08:48 Rather, once we call this fetch authenticated user function, it'll actually set the isLoadingState properly.
00:08:55 So in this case, all we care about is that state so we can check if.
00:09:02 not fonts loaded, or if still loading, then don't return the screen.
00:09:09 It means that we still haven't finished the necessary actions in order to be able to load the screen.
00:09:14 And then the second place where we can add a redirect check for a non-authenticated user, now very easily using this odd store,
00:09:23 is where we initially mocked that data.
00:09:26 It's within app, tabs, layout.tsx.
00:09:31 Here we just hard-coded it, but now it's super easy to get a real value by saying const, destructure the isAuthenticated field,
00:09:41 and make it equal to the hook call of the useAuthStore.
00:09:46 And now this is referring to the real value.
00:09:49 And if your component name is underscore layout right here, then you can change it to something like tab layout in this case,
00:09:57 because that follows the proper React guidelines for naming components, and therefore it knows that it can accept some hooks right here.
00:10:04 Perfect.
00:10:05 Similarly, we can now head over to our Auth layout, and also implement this check.
00:10:12 This one is maybe even more important because, hey, we're now looking at an Auth screen, but we're actually logged in.
00:10:19 At least we should have an active session from when we logged in the last time.
00:10:22 So right here, I can just say const isAuthenticated, is equal to useAuthStore, and then we can check if isAuthenticated is true,
00:10:36 then we can just return the redirect over to forward slash, meaning the home page.
00:10:43 And you can also rename this to auth layout.
00:10:46 So now if you save it, you can see that we automatically get redirected back to home page because our user is actually logged in.
00:10:54 If you haven't, you can log in and everything should work properly.
00:10:58 To test this out, you can add a console log in the home screen to see if there's actually a logged in user.
00:11:05 So if you head over to tabs, index.tsx, you can now very easily extract this real user from the AuthStore by saying const destructure the user from the
00:11:19 call to the use AuthStore hook.
00:11:22 Make sure to import it.
00:11:24 And then you can just console log the user like this.
00:11:29 And this user typically contains a lot of data, but you should be able to see it within the terminal.
00:11:34 In case you want to be able to see it in a bit of a more structured format, what you can do is say console.log user and then you can json.stringify this
00:11:45 object by saying json.stringify user pass null as the second parameter, which is a replacer, and then 2, which is for the spacing.
00:11:55 So if you do it like this, you should be able to see a very nicely spaced log for your currently logged in user object with all of its permissions,
00:12:05 database and collection IDs, avatar photo, account ID, and more.
00:12:10 Perfect.
00:12:11 So now we can get access to this user from every single screen within our application.
00:12:17 This is exactly what we wanted to achieve.
00:12:19 And doing that with Zastand, as you can see, is super simple.
00:12:24 You just have to declare this, I would even dare to call it a global object, and you can just use it whenever without having to repeat all of these calls
00:12:32 in every single page.
00:12:33 You just call them once or you call them whenever you need them, and it serves you the data on the platter.
00:12:39 And with that in mind, you now know how to implement a global storage or state solution in your React Native applications using Zustand.
00:12:48 Great work.
00:12:49 In the next lesson, let me teach you how to implement a tab navigation.