Enjoy free content straight from your inbox 💌
00:00
You can manage server side state in next JS by using an external data storage solution, an example, a database, and with next JS you can pretty much use any database that you want. You need to have your database hosted externally from your next JS application and you can host it yourself on a cloud platform like AWS or Azure or User SA provided dedicated for the purpose of database hosting like Neon or Planet Scale. Let's demonstrate the workflow with Neon as an example. There are a few reasons for using Neon. First off, it is the database hosting provider
00:33
that we use at Bullion Art. It is essentially Postgres TV on the cloud and Postgres is the most popular database nowadays and the reason specifically using it for a beginner tutorial is that it comes with a nice free plan. This means that you can create an account for free and follow along. Once you sign up and log in, you will be able to create a new project we are calling our project course dash next year. As from your project dashboard, you will find the option to get the connection details for your database. And the only thing that you need in order to connect to the database from your next JS application is the connection string.
01:04
We've already looked at how you can manage environment variables in XJS with CI ICD integration, but to keep things simple, I'll manually put my credentials in a dot and if not local file, we create a new environment variable called DB URL and paste in our connection string. I've blurred out the password for my database and if you want to play around with the sample code for this lesson, you need to provide your own DB URL, which as you've mentioned, you can get for free. If you are working with a relational database, likeon Postgres, you need to create the relational schema before you can start moving around some data.
01:36
Neon comes with an online SQL editor and we can use it to provide the commands to create a new table called to-dos. It'll have an ID field which will default to a new good A completed Boolean, a message text along with the created edge time, which we default to the time the item is created. We can even look at our tables and modify them from within the neon console. Now that we have the reduced table, we can add a new record with the message set to buy milk. All of the other columns within our table will automatically get default values as we specified in the schema. Once we save the record, you can see
02:10
that our new road was created. Now that we have a database set up, let's connect to it from our next year's project. For any database you need to install a database driver, which will be your main API to access the database. Neon provides its own drivers for using it from a serverless node J environment like next year's and we can install this driver as an NPM package, which we save to our project. Let's use this within our XDS application. We start off with a use of a directive as some of the functions we export we plan to use from the client. We import the neon API from the database driver. Next we create a utility
02:43
that initializes this driver using our connection string. This returns a function which we can use to execute SQL commands. Next we define the TypeScript type for our database records and as we know, it'll have an ID of type string message of string completed bullion along with the create That date. Let's create a server function that returns all the to-dos. We get the SQ utility and then execute the command select star from dues and we order it according to created add so that we get a stable response every time we run this query. We could over engineer this example and add an OM to ensure that the result types match,
03:17
but let's keep things simple for now and manually use a type assertion to tell TypeScript the contents of the results. Just like we can read the data using the API provided by the database driver, we can also use it to update the data. First off, we create a server function that will create a new to do and as we know, all of the other columns will be provided default values as specified in our schema. As a part of our query, we get it to return these newly created values, which allows us to return the first item from the results as a new todo. Next we have utility that updates the completed Boolean offer to do with a given id.
03:49
Using an ID ensures that we update the correct to-do, which is why you should always have a unique ID for your items as we specified in the schema. Once you have completed A to do, at some point you would want to get rid of it, which is why we create utility which deletes a to do with the given id. As you can see, it is pretty easy to work with Neon from our next year application. Given some basic knowledge of SQL with our database UTIL is created, let's use them from the react side of our application. Here is a sneak peek of the final user interface that we are going to build. We start off by importing our get todos utility and then within our page we use this utility
04:22
to load the initial to-dos. Next we pass them to our client component as an initial prop. That's it for our server page. Now let's create the client component. We start off within the context of a use client directive. We import some styles that will make our UI look a bit more pretty and then we bring in use state provided by React, which we will use to manage the client side state. Finally, we bring in the server functions which will allow us to make modifications to the database by making client side function calls. Before we work on the full ui, we will create a utility component designed to display only a single to-do. It takes a single to-do as a prop along
04:56
with mutation functions to mark the to-do as completed or deleted entirely. Within the component, we render out a list item that contains a root diff wire to a function that will toggle the completed state and within this we render out the checkbox that displays the current completed status along with the paragraph that displays the to-do message. On the right hand side of the simplest item, we render out a button which is wide to delete the given to-do With this core component created, let's build the complete user interface for our to-DOS app. The root client component accepts the initial to-dos from the server as a prop.
05:30
We then use it to initialize a client side state with use state. We also maintain the local state for a new to-do message that the user might want to add. Next we make the utilities that will make the API calls and synchronize the local state. The first one is create to do, which takes a look at the local message and if it is not present, it aborts the operation, otherwise it lays the value, makes the API call and then updates the local to-do state with the server returned to do next. We have a utility that updates the completed status of the to-do and for this it simply makes the API call and then updates the local state.
06:02
Finally, we have the delete utility, which simply deletes it by ID and then removes the to-do with the given ID from the local state. With these utilities created, let's run out the dorm for our main application. We start off with a simple root div that contains the form wired to create a new to-do. The form will contain an input that the user can use to provide a message for a new to-do along with the submit button, which can be used to submit the form. We follow this with the divider used to separate the form from the list of existing to-dos and all that we need to do now is list
06:34
out the existing to-dos. We map over the to-do items in the local state and for each of them use the display to-do component that we created previously passing in the required props, which are wired to our utilities and that's the entire front end code of our application. We basically have a component that displays a single to-do and then a root component that maintains the client side state while making the necessary API calls and then renders out the full UI while utilizing our display to do component with our code out of the way. Let's play around with this application. Within the browser, you can see that our initial to-do,
07:07
which we created using the neon console, has been noted successfully. We can provide the message for a new to-do and then click create to add it to the to-do list. We can mark an individual item as completed by clicking the text or the checkbox. And finally we can even remove a to-do by using the delete button and all of this is being persisted to the service date, which is the database, and we can verify that because when we refresh the page, the initial to reduce return from the server matched what we were seeing before.