Global State Management in NextJs 14 Using Zustand

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
in this video we're going to talk about global State Management in nextjs using zustand we're going to create this task tracker where you can create new tasks for example buy fruits and then adding a little description maybe the type of fruits that you wanted to buy you can create more to-dos if you want for example another task once you create these task you'll be able to actually drag and drop them in different columns which represents different status or different states for these tasks and the Border color actually changes showing that these tasks under the hood are actually changing the state is actually changed now all of this Global state is managed by Zan which we're going to dive into in a second but before I get there I want to mention the inspiration for this video I watched this video from Nicholas over at free Cod camp where he's building something similar using zand as the global Estate Management for the react app he's creating it I took that project and brought it to nextjs if you're recreating this with typescript and tailin CSS to actually see how that implementation works in nextjs we're also adding a middle ver to persist this data into local storage so if you refresh the page your tasks would still stay the same so this is a fully functional app that somebody can actually really use just using their local storage and at the end I'm going to also mention a problem that you would encounter when you wanted to persist this data on local storage specifically nextjs because nextjs server renders your components and it's a bit different uh in a way how uh pure react applications work in that you would have some hydration mismatch from what was rendered on the server and what's rendering on the client because we are now reading or persisting our state to the local storage inside the browser which our server doesn't have access to so the UI or the HTML that was generated at on the server is different from what's generated on the client so you have to uh skip the hydration on the server and then do it on the client site so at the end I'll also mention how we're going to go about that but I wanted to um kind of shout out that video um from Nicholas over at free Cod camp that inspired for me to create this video I've also had questions or folks asking me about global State Management in nextjs so I thought this may be a good reason to create this video now over the videos we had on the channel we discussed about the need for a global Estate Management with this new paradigm of actually server rendering uh your application and your components in the app router index js4 now uh which doesn't require as much Global Estate Management as before when we were rendering primarily on the client site you're fetching data on the server you can use the URL as a place to hold your state or communicate your state from client side to your server site we've seen this for filtering for sorting for searching for pagination and actually using the URL as our state and a good way to communicate between the client and the server but nonetheless if you need to use a global State manager for uh one reason or another zand is actually a simple API you can use is a simple interface you can use to actually manage your state globally on a client s side persisted into local storage or even persisted into a remote storage into an asynchronous storage if you want to you can also use it to persist it in the URL if you want to uh so there's different things you can do using the middle verse that comes with Zan that we're going to see uh together but nonetheless if you wanted to implement Global State other than react context combined with the used reducer that comes built in from react a library or an API like can help you simply put a global store that you can tap into as a hook from different component inside your app so with that out of the way let's just jump into the zand documentation and see what this is all about zand as I mentioned is a small and scalable State Management solution it is similar or an alternative to Redux in that it is following flux principle so it's a flux like State Management tool but it is very easier to implement compared to Redux and it's way smaller and faster than Redux in my opinion in terms of the library and but also in terms of the developer experience so to install it you can just go ahead and install zand and once you create or once you install the library you can create a store in a single file like so so you get the create function out of the library and you're going to call this function which is going to give you back a hook which you can use in any component that needs to subscribe to to this state to this create function you have to provide a call back function this call back function receives a Setter or a set function from zustand and whatever you return from this internal call back function is going to be your state for example here we're setting Bears to zero then we're also putting into actions or returning or including two functions as part of our state and this is something that's different here from Redux in Redux you have to Define your actions separately here you just Define them all in one file actually inside one state now this first function or first action is a function that's it's a function that's calling the set function to the set function you can pass in the new state or the new piece of the state that you wanted to change I'll come back to this uh syntax for a second but look at this uh function down here where we setting Bears to zero and the set function actually merges the state for you so it is following an immutable State um principle similar to Redux but the set function actually does the merging for you so you don't have to worry about spreading your um previous state and then uh returning a new state you could just set the piece of State you wanted to change and the set function is going to take care of the merging for you or if in your your new state you depend on the previous State's value like so in here you can pass a function to your Setter or to your set method where you would have access to the previous state then you're going to return a new object for example bear here is just incremented whatever number of bear that we had previously or currently in this state um to then return this new piece of state and then merge this whole thing with our state okay so this is how you create an store we're going to implement this in our own application uh shortly but let's just uh go further and see how we're going to actually bind our components or subscribe to this estate from our components now one thing another thing that this is different from Redux is that you won't need any providers so you know for Redux you have to wrap your application with providers so your components can actually hook into the state for this for Zo you don't need a provider and all you need to do is to import this use store hook in any component that needs to tap into or subscribe to your state and then to this you can pass a function that receives the current state and actually select that piece of state that this component is interested in so instead of returning the whole state here we're just returning the Bears therefore anytime the Bears changes this component that subscribe to Bears state is going to render now this is a pattern for select cting that piece of state that you're interested in or that that component is interested in to prevent unnecessary renders and in Redux this is done using the use selector hook but here is very simple you just tap into the state and get the piece that you want for example in this bare counter now down here is another example of a component that's actually getting this increased population function and actually binding that into the onclick method of this button so we can increment M the population of our Bears so this is all you need to do to actually create a store and then use that state inside of your application so let's jump inside of our code and see how we would go about implementing this in inside our own application now I've gone ahead and created an xjs application using typescript and Telvin CSS and I've already implemented this basic shell for our Canan board so we have a good starting point point and we're going to wire this up with our Global state in this video step by step but if you want to follow along with me you can actually go to the link in the description uh for the source code there's going to be a branch called start and this is where we're starting right now here you can actually see the end result in the main branch uh once we're done so let me just close this off going back to our application so let's actually see what I've done so far so you can get up to speed with me so the layout is exactly what you get out of the box uh installing the next jss script so the first thing that we're doing inside of our homepage everything is is inside our of our homepage so let's start from this page I've implemented this columns which is holding my different columns uh now each of these columns that are different states of our board or these to-do tasks have a title as you can see the to-do in progress and done and have a status that corresponds to the title so it's to-do in progress and done done we're going to come back to this when we're actually creating our Global state so every column has a status and a title let's go inside of each column now here I have just created this uh demo or dummy task tasks array so that I can actually uh show it here so all we're doing inside of each column is actually getting our tasks which is this array we created here filter it based on the task that actually share the same status of that specific column and then mapping over those filter tasks and for each one we're going to show this task component before I get to this task component just want to mention here because this one task that I had here had the status of done it's showing up on the last so if I change this to to-do for example this just jumps uh to the first one because again we're filtering the tasks based on the status of that specific column now let's actually also see what's happening inside of our task now here we're just rendering uh the title of the task the description of the task and then this little delete button that doesn't do anything which is supposed to then delete this specific task now here I'm also using this CN function which we're going to uh look at it in a second to conditionally just add different border colors as I mentioned if you move this to different states or different statuses the Border color actually changes now let's look at this CN function it is using Telvin merge and also uh the clsx library to not only conditionally add these CSS utility classes but also merge them together when we have duplications so I've created this lip folder inside of it there is a utils for folder this is a pattern uh that we have seen and implemented when we're working with shat CN Library we're actually using some of the shat CN components inside of this I'm going to explain when time comes but basically what we're doing here is that we're passing the inputs these are our class names to this CN function which is going to run them by clsx uh and then the Telvin merge to conditionally apply this classes and then merge them if there's any duplication that out of the way in the task so we're just basically uh rendering different border colors depending on our state and this is all I had done to this point in the next step we can bring in zo stand and create our Global state so we can wire it up to our components so let's go to the documentation to add this we have to install zand so let's just stop the def server here and then pmpm add zand okay great so let's PM PM Dev again let me also close this up we're going to go out and maybe inside of our lib I can create a file called store. TS where I can actually import the create function from zand and now down here we want to export our hook which is called use task store and this is going to use this create function and we're going to pass some types to it and our call back function which is going to actually return our state now before I go ahead and actually complete this function to define the state we want to manage with this hook let's actually create our types so I'm going to export a type called task this is how our individual tasks would look like so we're going to have an ID of string we're going to have a title string we're going to have a description of again type string and then at the end we we can have the status which is going to be of type status so let's actually also Define this type status up top so I'm going to export another type let's call this status this is going to be a union it's going to be to-do or it's going to be in uncore progress or it's going to be done and this status here is going to be of that type status that we defined there then we're going to Define uh the type of our state so our state is going to have an array of task like so and also let's define some actions so Define type actions these are the functions that we're going to to expose that actually updates our state so we're going to have the add task which is going to take in a title of type string and a description of type string let me just close this off so we have more room here and then this is going to return void let's also make the description optional so this is add task uh we're going to have one for removing our tasks this is going to take an ID of type string and again is going to return void next we can expose an update task action or function that takes in an ID of type string and also a status of type status and then also returns void so these are the actions we need for now we're going to add to the this actions when we want to actually uh have the drag and drop functionality but for now we have the add task remove task and update task so now that we have these types let's actually type our store this is going to be of type State and actions now when you wanted to add types to your store you add these uh curly braces or brackets to your types so for everything to work correctly there 's a part in the documentation where it explains why you would need to do that or alternatives to do this which is to using the combined function to combine uh the types when you're using middle verse uh I would leave that to you if you wanted to review and now here we get the set function and what we want to return from this function is tasks so we have the array of tasks we can start from an empty array we can also add our actions here so we have the add task remove task and update task now let's go ahead and actually wire up these actions the add task requires a title of type string and also a description of type string and this is going to actually go ahead and call the set function to this we can pass in a call back that actually returns a piece of State it's going to receive the current state and here inside this piece what we want to do is that we want to get or reset our tasks to be whatever that we had inside of our state. tasks and then we want to add something new to it we're going to give it an ID we're going to use the uu ID package in a second but for now let's just pass in title description and then let's default the status to too to begin with uh now there's an error here because the description here needs to be optional and also inside of our task the description is optional so maybe somebody just passes a title and not a description so what we're doing here again is we receiving a title and a description optionally we're calling this set function that comes from zand to this we can pass in an internal call back that receives the current state we're going to return this piece of object that is going to be merged to our whole state inside of it we're going to rewrite the task array we're going to get everything that we already have and add a new one uh to the end of it now let's use The UU ID package here to actually add this ID so I'm going to stop the def server add pmpm uu ID okay let's restart the dev server close this off actually go up let's import this uu ID here and now instead of passing in one two three we can call call The UU ID function so this is giving me an error because it does not have the types for The UU ID package so let's just stop the dev server once again and actually pmpm add- D the types for uu ID okay this should be good now rerun the dev server close this up yeah that error is gone so that was our first um action the next one the remove task is going to receive an ID of typ string and again it's going to call the set function this is going to receive a call back that's going to return a piece of state and we're going to get our current state here and inside of our object we're going to set the tasks to be uh state. tasks. filter we're going to get the task and we're going to return everything uh whose ID actually is not equal to to this ID that we have here so let save that up preview again so we receive an ID we call the set function receive the corent state we're rewriting the tasks array by filtering all of our tasks whose ID is not this ID that we have passed here so we're just going to filter that specific task out of our array now the last one the update task is going to receive an ID of type string also is going to receive the status this is going to be off Type U status and this is going to again call the set function this is going to receive a call back and is going to return a piece of State it's going to also have access to the current state and inside of here we're going to set the tasks to be state. tasks and then we're going to map over our tasks and for each one if the task. ID equals this ID that was passed we're going to return that specific task and we're going to rewrite the status otherwise we're just going to return the task so let's save this up and review our update task is going to get an ID this is the ID of a specific task and a new status which is of type status these are the type of our status that find up there it's going to call the set function which receives a call back that has access to the current state is going to rewrite the tasks array by mapping over our current tasks and rewriting the task that has this specific ID with this new status or and returning all other tasks unchanged so this is all we need to create this store which is exposing an array of tasks and some functions or actions to add update and remove tasks from our state so let's actually go to our column component where we were actually using some fake tasks and hook this component using this hook to our Global state to use the tasks there so here I'm going to just get const tasks and this is going to be use tasks store from our lip this is going to receive this state and we want to return state. tasks I can remove that instead of mapping over that it's going to filter these tasks depending on which one has the status of this specific column we can also wrap this inside of a use memo so we only recreate or recalculate this filtered tasks only if this a specific tasks array has changed so let me just close this off so I'm using use memo it receives a function that computes a filtered array um to this we have to also pass in the status and it's going to only recompute this filtered tasks or filtered array if the task or the status actually changes now we can use this filter task to map over and use this task now let's see what this area is here inside of our tasks okay so again this description is optional all probably this is why okay so now we mapping over our filter tasks and rendering a task now going to our application we shouldn't see anything now if you refresh because we don't have any tasks currently set inside of our state so the next step is actually to provide a way a form a model for the user to actually add a new task but before we get there if you're using this use task store hook inside of a server component we need a client component to be able to use hooks or react hooks so I have to turn this component into a client component by adding this use client directive up top and now we have our application back but we don't have any tasks here so let's actually go back to the columns and start adding a way for the user to be able to add a new task so let's wrap this up with a div and then I'm going to copy over a component that's using shat CN uh to actually use um a model and a form to add new tasks let's also bring this in here let me just add that here and then we're going to import this from our components and for this we need to install shat CN so let me just open this up I've talked about chaten before it's a component library that you can copy paste different components already made and styled components with ton CSS into your project for example if we wanted to use a dialogue which is a model that we're going to put in some Fields inside for the user to be able to create a new task you can just come into dialogue and here you can see the code that is responsible for this abstraction and to copy this or to install this you could use this terminal command which is going to copy this code inside of your project but before you uh before you can do this you have to install a shat CN in your project so in the INT in installation there's a guide for xjs you just go ahead and run npx Shad CN UI at latest and initialize your function this is going to add a couple of uh dependencies like radx UI cuz this is built on top of radic UI and it's also going to add a component Json file which is a config file for shaten to understand how your project is set up are you using the app router or not are you using the source directory or not and then you using that it's going to then create a UI folder inside your components to then add these uh components that we using to our project so let's actually go ahead and do this together I'm using pmpm so you can click and copy the pmpm code here just close this off stop the dev server and copy this in it script let me close this off so actually we see what we're doing here this is going to ask us how our project is set up whether or not we using typescript so let me just back here yes I'm using typescript um let's use the New York style our default gray is let's say gray Global CSS is inside of our app just so you know this is the app and then inside of it you have this Global CSS it is going to set some Global CSS if you're using or setting up your project with Telvin uh which is basically it's going to write the tail in directives to reset all the browser specific styling is going to do the same thing whether or not you want to use CSS variables if you're using theming I'm not using it for here and also asking you where is your telfin config which is on the root of our project our component is living actually at the components Li utils the same thing and are we using react server components yes and should it proceed with the component. Json which is the config for shat CN so this is the first step let's go back to application and see the diff changes that this has made to our application so as I mentioned this component Json is actually the structure or the settings that we want to use from chat CN inside of this lip it's going to add this CN um function that we just saw together in the beginning of the video and it's going to also add a tailin config for you now because I already had it it added it as as a JS file I already had it as a TS file I'm going to save this delete this old one and rename this new one to use the TS so that's all and good let me just save this up inside of this new uh to-do dialogue uh as I mentioned it is the button that we saw in the beginning of the video which you would click on it opens up a dialogue a Model A model inside of it there is a form some input some text area to add a new task so this is basically copying uh what you can see on the chat and if you go to the dialogue um you can see a sample code of this dialogue opening up has having some input Fields I've just replaced it with the titles headers descriptions and inputs that I needed um and a button that actually submits this form that we have here we're going to hook this up with our state to actually upon submission actually add a to-do and close this dialogue going to see that in action but from a high level this is what I've implemented here we need to actually install the dialogue input and text area so let's go to the dialogue and for installation all we need to do is to run this terminal command so we're going to go to our terminal and actually copy that code here okay the next thing we need is an input so let's go down to the input again copy the same code the pnpm let's actually copy this here as well and while this is installing we need the text area as well so I'm going to scroll scroll down go to the text area again copy the installation script and then here I can install the text area or copy over the text area into my project and all this is going to do is to create this UI folder for you and it's going to copy this newly created component here let me just restart the dev server okay let's close this up now the good thing as I mentioned about chaten is that it gives you access to the Primitive so so you can just dive deeper into uh the parts and components that compos together to create for example this model you can change stuff in it down under the hood it's using radic UI so as far as the API goes if you wanted to add any function that you can reference radic UI and as far as the styling goes it's just using Tel CSS so you can just go in and change anything that you want about it and that's how it's a bit different from a component library in the sense that it just exposes a component you can use uh often times they they're going to give you variants and attributes that you can set but you can never go in and change them from the ground up whereas here you're not installing anything you're just copying literally components or abstractions on top of radic cui and Tel CSS to your project and you have absolute control to change anything you want about this so let me just close this off going back to our uh new to-do Library we need the button as well so last thing here let me go up and actually also install the button so open up the terminal stop the def server copy the code here install the button let's restart the dev server okay now we have this add new to-do button here that opens up this model where we have an input and a description to add a new task now one thing that I want to change here is this overlay or the backdrop of this model so I want to go inside of our dialogue and change that so I'm going to click on this and and then here you can see we have this overlay right now it's rendering a white background maybe I want to change this to be a gray 700 because it goes better with my application so that's what I meant that you have access or control over how they look uh deep down inside of each of this compartments of this component because it's just copy to your code nonetheless so now that we have this form let's actually also explain how we have hooked it up when this form is sub it to add a task so we have a form inside of our dialogue this has an input of title and a text area for description we have a button of type submit inside of the dialog footer this is going to actually submit our form which is wrapping or it's inside of this dialogue and on submit we just calling this handle submit function inside of this handle submit all I'm doing is to get my tolerant description so the two inputs from the form and then I'm calling this add task function or action from my store to add a new task and I've used this use task store hook that zo gave me back when I created my store and I'm specifically getting the add task function or action from it and I'm just invoking that by passing a title and description and if you remember inside of our store if I go to the lip this is the definition of our add task it takes in the title and description and just adds that to our array of tasks now other than that I'm just passing in some types preventing the default behavior of our function and actually down here making sure that this title and description field are string because they can also be of type file from your form but this add task action or function from our store requires strings okay so with this if I go ahead now and create our first task and some description this should add it to our to-do and because we defaulting it to the state of to-do it's just inside of our first column but right now we cannot drag this or update the status of these tasks so let's actually Implement that next now in order to make our individual tasks draggable we can come to the tasks component and inside of this div we can just pass in the draggable attribute which is going to instruct the browser that this specific div or component is draggable now you won't be able to see it here but I'm actually dragging this item around for some reason it's not visible in my screen recording but that's the first step to make this task draggable but the second piece of this logic is for us to know and track what task is actually being traged right now so we're going to go back to our store and actually hold another state for that specific task or for the ID of that specific task that is being dragged so let's go back to our store add another piece of state to track which task is being dragged so I'm going to add dragged task this is going to be of type string it's going to be the ID of the task which is being dragged right now so now that we have this state let's also actually return it from our store function as well so we're going to have the drag task and this is going to let's say start off from null so that's actually also this adding here so to begin with nothing is being dragged so it starts off with null but it can also be an ID of a specific task when the user actually starts to drag this around so let's also add an action that Updates this state so I'm going to call this drag task this is going to take in an ID of type string or just be called with a null um value to set this drag task back to null so let's also add this action down here we're going to say drag task again this is going to be a function that receives an ID with a string or null and then what this is going to do is call the set function and actually set the drag task to this ID that was passed to it let's also pass this in save this up so let's review what we had done we added another piece of state to our state or to our store to track if any task is being dragged and save the store or save the ID of that t of that task in this piece of State we also added an action which is going to take an ID and actually go ahead and set this piece of state to the idea of that specific task that is being dragged so now that we have this piece of State let's actually go inside of our task component where we marked it as draggable and actually listen to UND drag event and here we want to call that function that we just defined to actually set the ID of this specific task to be the one that's being dragged so let's go up top here we're going to get that function we just created called drag task and we're going to get this from our store so use task store and this is going to get this state and and from it we want the drag task function so when the user starts dragging this component we want to call this drag task function and pass the ID of this specific task which is being dragged now which means we need to pass the ID here we already passing the ID so let me just destructure it here and the ID would be of type string I just also add a comma there so what we're doing here again we're getting this drag task function or action we just created in our store and anytime the user is actually dragging any of our tasks we want to pass the ID of the dragged task and hold it inside of our state so therefore when we're listening inside of each column for a drop action we know which ID or which task is actually being dropped so therefore we can update that specific task tasks status to be to do in progress or done depending on where it is being dropped so let's go back to our columns now and actually make our columns droppable so we're going to come to this div and we're going to say on drop let's call handle drop so handle drop what do we want to do here well we want to update this's a specific task that's being dropped here so so let's actually get this update task function from our store so update task it's going to use the task store it's going to get the state and it's going to tap into this update tax task function now down here it is telling us that this needs an ID this is a specific task that's being dropped and needs a status well where do we get where can we get the ID where we holding a piece of State for the actual task that's being dragged if you go back to the store this is the dragged task and we have updated it inside of our task anytime any of our tasks were being draged so therefore we can actually tap inside that piece of State as well to get the dragged task again using our task store we getting this state and we're tapping into to the drag task so now we can pass this as the ID and then the status is the status that we passing into this specific column so that we are using that as the status now this drag task actually can also be null cuz when we begin it is actually null there is nothing being dragged so we need to check to see if we actually have this so I'm going to say if there is no dragged task let's return from this function and do nothing and if this exists we're going to actually update that task now we have an error here because the status is not actually of type string it's a union of type status we can import this from our lip this going to be the same type that we created here so we can now use it inside here and once this has updated that task it has been dropped into a new column with a new state or with a new status we need to to then call this drag task function and set it back to null cuz nothing at that point once we drop it nothing is being dragged so we have to set the ID of drag task back to null so we're going to also get that function which was called drag task uh use task store just going to get this state and actually tap into the drag task function where we can call that function and pass null to it okay so let me review what we're doing if it was a bit confusing the first St step we added a piece of estate to our store so we can store the ID of the task that's being dragged we also added a function that just updates that piece of state anytime the user is actually dragging a task inside of our task we added this draggable to make each of our tasks draggable and then every time the user is dragging them we want to call this drag task function from our store and pass the ID of that specific task that being dragged around now inside of our columns we want to actually listen to drop so when this task is actually being dropped into a column we added this undrop event handler and inside of it what we're doing is to see if you have the ID of the task that's being dragged and if you do we want to update that task that is now dropped into the this column and change the status of it so we pass the ID this ID is coming in from our state again it was updated when the task started being dragged and then the status is coming in from this column cuz each of our columns remember have a specific status and then at the end once we updated that specific task that was dropped we're going to set the ID of the dragged task back to null because nothing is now dragged now one thing we wanted to or we have to add here for this to work is when we are dragging over this columns we want to actually prevent the default this is something that I actually learned from the video I mentioned in the beginning so you would prevent the default so nothing would happen when you're dragging over or columns but when we actually drop and release the mouse we want to actually update that specific task so let's go ahead and see if this is working if I now create our first task here and add some description and now if I drag this over to our progress or in progress column it actually drops there and updates the state because now the border is yellow if I take it to the done it will be green which means not only VI dragging and dropping receiving this estate in different columns but also updating it under the hood so it changes the state using our event handlers now let's also hook up this little delete button on every task to actually call our function and delete right now on this button we're not calling anything so let's actually come in here and get the remove task function from our store again use task store this is going to get our state and from it we're going to get the remove task function and all we want to do here inside of our button is to add a onclick event listener which is going to call this remove task function and passes the ID of this specific task that we are actually rendering here so now with this if I go ahead and click this delete button it should remove this from our task list now the last thing that I want to add to our application is the ability to persist our store data in the local storage in the browser so if the user refreshes the page they're not going to lose their tasks because as of right now if you add a task and refresh the page it's just all gone at the end of the day this is all react State and when you refresh the browser it just gets rid of all the state now we can process this data into the local storage and read it from there so therefore the user uh if refreshing the page is not going to lose their work or their tasks now going back to the zand documentation you could just go uh here to their middle ver section where they actually talk about persisting store data so they expose some middle ver that you can use to persist the data so if we're going to use the default local storage so all you need to pass in is this name and because this is going to use the default and the default storage is going to be the local storage so we don't have to pass that let's actually go back to our store where we can use this persist midle function to actually save our store into the local storage so I'm going to get this persist from the zand midare package and all I'm doing here is wrapping this set function we had before which is going to return our state and then passing a second options object to this persist middleware which I'm defining a specific unique key that's going to be used to store our state or our store inside the local storage okay so let me just save this up and now if I go back to my application I can see that I have had some previous States or store written to the local storage so it has picked that up as well and if I refresh the page now you''ll be able to see my tasks are there but now we've introduced another problem and the problem is some hydration errors now this is what I mentioned in the beginning of the video because nextjs actually server renders or components and then hydrates them on the client side on the server it doesn't have access to the local storage so therefore the HTML is not or the UI is not the same from what the server got initially and what the client is rendering there so that's what this hydration error is talking about so if you come back to the documentation and actually scroll down on this same page you should be able to see an option to skip the hydration when you're initializing your store so here we can pass in this uh option to the second parameter we provided to the persist middle okay let's set this here now let me explain what this means now hydration in the cont text of your zon store is actually or persisting data is when it reads the local storage retrieves that uh stored data and actually merges that with your current state so when you're initializing the store for the first time it actually reads the storage and then merges whatever it is in your local storage with the current state now this is going to cause an error because when we are server rendering our application on xjs this our server doesn't have access to this data on the local search because it's not it's inside the client side in the browser so therefore the UI that's sent from your server is different from the UI on the client side so we want to disable this reading from the local storage when we're initializing our store our zon store but once we do this we have to also remember to hydrate it after so we want to do this hydration only on the client side using a use effect once we have actually mounted our client components which is the second piece of this where you would need to call this use client so let's go to our column component and actually get this uh use effect and let me actually also import this use effect from react and now what we're doing here is we're accessing our store we are accessing the persist middle ver on it and there is this rehydrate function on it where you can call to make sure this is only reading from your local storage once this component has been mounted on the client side so therefore there's no clash of the UI between the server and the hybrid Vision version of the client s so now if I go back to my app if I refresh I see my tasks there but I don't see any hydration error I can delete this tasks or add a new one I can drag them over I can update their states and our application is fully working now that's a wrap for this video folks I know we covered a lot from managing our state using zustand which is a global State manager the implemented that inside our nextjs application which was using server components for rendering our pages but we also needed to turn the components that actually need to hook into this store to a client component because it's a hook anytime you need to use a hook or any of react hooks you need to use client components so we turn those components that needed this functionality to client components now good the good thing about zon was that it didn't need a provider kind of context provider or a provider component so we didn't need to wrap our whole app with the providers anytime any component that needs to use any piece of this estate you would just use that use store hook that it gives you back once you call the create fun function and you can tap into And subscribe to the piece of state that you're interested in we also added that functionality for us to drag a task over and drop it inside of a column which eventually would update the status of that task if you have any questions hit me up in the comments I hope this was helpful and I will see you in the next one bye-bye
Info
Channel: Hamed Bahram
Views: 10,192
Rating: undefined out of 5
Keywords:
Id: BxohoXjbhKc
Channel Id: undefined
Length: 51min 16sec (3076 seconds)
Published: Tue Nov 14 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.