Using Databases for Dynamic Server Side State

Account Required

This free lesson is available if you sign in.
If you don't have an account, you can sign up for free.

Professional NextJS Lessons

1.Course Intro
free
⏱️ 2:05
2.Get Setup
free
⏱️ 2:05
3.Project Template
free
⏱️ 5:45
4.Introducing FullStack React
free
⏱️ 4:57
5.App Router Reference
free
⏱️ 7:08
6.NextJS Server vs. "use client" Rendering
⏱️ 5:01
7.Nesting Server and Client Components
⏱️ 8:51
8.Client Only Components
⏱️ 3:48
9.Global CSS in NextJS
⏱️ 6:30
10.CSS Modules and SASS
⏱️ 4:15
11.Tailwind CSS
⏱️ 5:17
12.NextJS Custom Fonts
⏱️ 4:08
13.Static vs Dynamic Rendering
⏱️ 4:55
14.NextJS Link Component
⏱️ 3:20
15.NextJS Link Prefetching
⏱️ 5:49
16.Navigation Scroll with Link
⏱️ 2:02
17.Replace Navigation History
⏱️ 1:35
18.NextJS Image Component
⏱️ 7:01
19.Dynamic Image URLs
⏱️ 5:34
20.Safe Colocation with Private Folders
⏱️ 2:12
21.NextJS Route Groups
⏱️ 3:07
22.Dynamic Routes
⏱️ 5:37
23.NextJS API Routes
⏱️ 6:03
24.NextRequest and NextResponse
⏱️ 2:41
25.Cookies in API Handlers
⏱️ 4:25
26.React Suspense Simplified
⏱️ 2:23
27.Power of Suspense Boundaries
⏱️ 3:52
28.use Promises
⏱️ 3:24
29.Stream Promise Results from Server to Client
⏱️ 3:03
30.use Requires a Cached Promise
free
⏱️ 2:30
31.Suspense Error Boundaries
⏱️ 4:42
32.React Server Functions
⏱️ 4:50
33.Server Actions for Powerful Forms
⏱️ 5:35
34.useActionState to Simplify Form Actions
⏱️ 6:38
35.React Serializable Types
⏱️ 2:42
36.Create Dynamic Images with NextJS ImageResponse
⏱️ 5:54
37.Deploy NextJS Application to Production
⏱️ 3:51
38.NextJS Environment Variables Masterclass
⏱️ 3:50
39.Deploying and Managing Environment Variables
⏱️ 4:38
40.Using Databases for Dynamic Server Side State
free
⏱️ 7:34
41.Mastering NextJS Layout Files
⏱️ 4:54
42.Client State Management with NextJS
⏱️ 3:48
43.Client State Management In Action
⏱️ 8:04
44.Using Client State Management Libraries
⏱️ 5:25
45.Detecting Server vs Client Runtime and useEffect
⏱️ 4:33
46.Demystifying ISR vs SSR vs SSG
⏱️ 3:07
47.Static Site Generation or SSG with NextJS
⏱️ 3:16
48.Incremental Static Regeneration (ISR) Simplified
⏱️ 2:51
49.API Routes Caching with NextJS
⏱️ 3:05
50.Reference Guide to Caching for Modern NextJS
⏱️ 2:47
🚨 Work In Progress 🚧
Subscribe for Launch

Using Databases for Dynamic Server Side State

Sign in to access this content

You must sign in to access this content.
If you don't have an account you can sign up for free!

Core Concept

You can manage server side state in NextJS by using an external data storage solution. For example a database server. And with NextJS you can use pretty much any database that you want.

You need to have your database hosted externally from your nextjs application

  • And you can do it host it on a cloud platform like AWS or Azure.
  • Or a SAAS provider dedicated for the purpose of database hosting like Neon or Planetscale.

Create a Database

Let's demonstrate the workflow with Neon as an example. Reasons for our choice:

  • It's what we use as BooleanArt 🫰🏻
  • It's Postgres in the cloud. Everyone loves Postgres ❤️
  • Comes with a free tier. Allowing you to follow along for free 🌹

Sign up for neon, and from your dashboard get the connection string as shown in the video. Move it into an environment variable using .env.local.

# The password here is masked with `*`, it is only an example string
# You'll need to provide your own connection string as shown in the video
DB_URL=postgresql://neondb_owner:******@ep-plain-art-a5nu4k5s-pooler.us-east-2.aws.neon.tech/neondb?sslmode=require

Setup The Schema

Before you can store and manipulate data in the DB, you'll to create a schema. We kept it simple, there is only a todos table you need to create:

CREATE TABLE IF NOT EXISTS todos (
id UUID DEFAULT gen_random_uuid(),
completed BOOLEAN NOT NULL DEFAULT false,
message TEXT NOT NULL,
created_at TIMESTAMP NOT NULL DEFAULT now(),
PRIMARY KEY (id)
);

Connect from NextJS

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 nodejs environment like NextJS and you can install it from NPM.

npm install @neondatabase/serverless -SE

Build your app

Now that we have the DB, all we need is to build our app!

The final code for the example used is shown below 🎉

lib/db.ts
.env
app/page.tsx
lib/ui/Components.tsx
lib/ui/Components.module.css
"use server";

import { neon } from "@neondatabase/serverless";

function getSql() {
const sql = neon(process.env.DB_URL!);
return sql;
}

export type Todo = {
id: string;
message: string;
completed: boolean;
created_at: Date;
};

export async function getTodos() {
const sql = getSql();
const results = await sql`SELECT * FROM todos ORDER BY created_at ASC`;
return results as Todo[];
}

export async function createTodo(message: string): Promise<Todo> {
const sql = getSql();
const result = await sql`
INSERT INTO todos (message)
VALUES (${message})
RETURNING *
`;
return result[0] as Todo;
}

export async function updateTodoCompletedById(id: string, completed: boolean) {
const sql = getSql();
await sql`
UPDATE todos
SET completed = ${completed}
WHERE id = ${id}
`;
}

export async function deleteTodoById(id: string) {
const sql = getSql();
await sql`DELETE FROM todos WHERE id = ${id}`;
}
javascript
typescript
react
playwright

Enjoy free content straight from your inbox 💌

No spam, unsubscribe at any time.

Transcript

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.

Professional NextJS

Professional NextJS

1.Course Intro
free
⏱️ 2:05
2.Get Setup
free
⏱️ 2:05
3.Project Template
free
⏱️ 5:45
4.Introducing FullStack React
free
⏱️ 4:57
5.App Router Reference
free
⏱️ 7:08
6.NextJS Server vs. "use client" Rendering
⏱️ 5:01
7.Nesting Server and Client Components
⏱️ 8:51
8.Client Only Components
⏱️ 3:48
9.Global CSS in NextJS
⏱️ 6:30
10.CSS Modules and SASS
⏱️ 4:15
11.Tailwind CSS
⏱️ 5:17
12.NextJS Custom Fonts
⏱️ 4:08
13.Static vs Dynamic Rendering
⏱️ 4:55
14.NextJS Link Component
⏱️ 3:20
15.NextJS Link Prefetching
⏱️ 5:49
16.Navigation Scroll with Link
⏱️ 2:02
17.Replace Navigation History
⏱️ 1:35
18.NextJS Image Component
⏱️ 7:01
19.Dynamic Image URLs
⏱️ 5:34
20.Safe Colocation with Private Folders
⏱️ 2:12
21.NextJS Route Groups
⏱️ 3:07
22.Dynamic Routes
⏱️ 5:37
23.NextJS API Routes
⏱️ 6:03
24.NextRequest and NextResponse
⏱️ 2:41
25.Cookies in API Handlers
⏱️ 4:25
26.React Suspense Simplified
⏱️ 2:23
27.Power of Suspense Boundaries
⏱️ 3:52
28.use Promises
⏱️ 3:24
29.Stream Promise Results from Server to Client
⏱️ 3:03
30.use Requires a Cached Promise
free
⏱️ 2:30
31.Suspense Error Boundaries
⏱️ 4:42
32.React Server Functions
⏱️ 4:50
33.Server Actions for Powerful Forms
⏱️ 5:35
34.useActionState to Simplify Form Actions
⏱️ 6:38
35.React Serializable Types
⏱️ 2:42
36.Create Dynamic Images with NextJS ImageResponse
⏱️ 5:54
37.Deploy NextJS Application to Production
⏱️ 3:51
38.NextJS Environment Variables Masterclass
⏱️ 3:50
39.Deploying and Managing Environment Variables
⏱️ 4:38
40.Using Databases for Dynamic Server Side State
free
⏱️ 7:34
41.Mastering NextJS Layout Files
⏱️ 4:54
42.Client State Management with NextJS
⏱️ 3:48
43.Client State Management In Action
⏱️ 8:04
44.Using Client State Management Libraries
⏱️ 5:25
45.Detecting Server vs Client Runtime and useEffect
⏱️ 4:33
46.Demystifying ISR vs SSR vs SSG
⏱️ 3:07
47.Static Site Generation or SSG with NextJS
⏱️ 3:16
48.Incremental Static Regeneration (ISR) Simplified
⏱️ 2:51
49.API Routes Caching with NextJS
⏱️ 3:05
50.Reference Guide to Caching for Modern NextJS
⏱️ 2:47
🚨 Work In Progress 🚧
Subscribe for Launch