With Next.js 13 introducing the new /app
directory structure, you can now perform server-side operations more seamlessly. In this blog post, I will walk you through the process of setting up a PostgreSQL client and making server-side database calls in your Next.js project using TypeScript.
Thank me by sharing on Twitter 🙏
Setting Up the PostgreSQL Client
To start, we need to install the pg
library, which will allow us to interact with our PostgreSQL database.
Step 1: Install the pg
Library
Run the following command in your project directory to install the pg
library:
npm install pg
Step 2: Configure Environment Variables
Next, we need to set up our environment variables to store our database connection details. Create a .env.local
file in the root of your project if it doesn’t already exist and add your PostgreSQL connection details:
DATABASE_URL=postgresql://user:password@host:port/database
Step 3: Create a PostgreSQL Client Instance
We will create a new file lib/db.ts
to initialize the PostgreSQL client. This file will be responsible for setting up the connection to our database.
HP 67 Black/Tri-color Ink Cartridges (2 Pack) | Works with HP DeskJet 1255, 2700, 4100 Series, HP ENVY 6000, 6400 Series | Eligible for Instant Ink | 3YP29AN
$36.89 (as of November 20, 2024 06:18 GMT +00:00 - More infoProduct prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on [relevant Amazon Site(s), as applicable] at the time of purchase will apply to the purchase of this product.)Nexus: A Brief History of Information Networks from the Stone Age to AI
$21.66 (as of November 21, 2024 15:46 GMT +00:00 - More infoProduct prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on [relevant Amazon Site(s), as applicable] at the time of purchase will apply to the purchase of this product.)Chip War: The Quest to Dominate the World's Most Critical Technology
$16.40 (as of November 21, 2024 15:46 GMT +00:00 - More infoProduct prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on [relevant Amazon Site(s), as applicable] at the time of purchase will apply to the purchase of this product.)// lib/db.ts
import { Client } from 'pg';
const client = new Client({
connectionString: process.env.DATABASE_URL,
});
client.connect();
export default client;
Fetching Data on the Server Side
Now that we have our PostgreSQL client set up, we can move on to fetching data on the server side within our Next.js page component.
Step 4: Create the Page Component
We will create a file app/page.tsx
where we will fetch data from PostgreSQL on the server side.
// app/page.tsx
import client from '../lib/db';
interface User {
id: number;
name: string;
}
export default async function Home() {
let users: User[] = [];
try {
const result = await client.query('SELECT * FROM users');
users = result.rows;
} catch (error) {
console.error('Failed to fetch users:', error);
}
return (
<div>
<h1>Users</h1>
<ul>
{users.map((user) => (
<li key={user.id}>{user.name}</li>
))}
</ul>
</div>
);
}
In this example:
- The
Home
component is an async function, allowing us to fetch data on the server side. - We define a
User
interface to type our user data. - The PostgreSQL query is executed directly within the
Home
component. - The fetched data is stored in the
users
array and rendered on the server side.
Handling Errors Gracefully
Fetching data from a database can sometimes result in errors, such as connectivity issues or malformed queries. It’s important to handle these errors gracefully to ensure a smooth user experience.
Step 5: Implement Error Handling
We already added a basic error handling mechanism in our Home
component, but let’s expand on that to make it more robust.
// app/page.tsx
import client from '../lib/db';
interface User {
id: number;
name: string;
}
export default async function Home() {
let users: User[] = [];
try {
const result = await client.query('SELECT * FROM users');
users = result.rows;
} catch (error) {
console.error('Failed to fetch users:', error);
// Optionally, you could set an error state to display an error message to the user
users = [{ id: -1, name: 'Error fetching users' }];
}
return (
<div>
<h1>Users</h1>
<ul>
{users.map((user) => (
<li key={user.id}>{user.name}</li>
))}
</ul>
</div>
);
}
In this enhanced version, if there’s an error fetching the users, we set a default error message in the users
array. This ensures that our application remains functional and provides feedback to the user.
Conclusion
Integrating PostgreSQL into your Next.js application and performing server-side database operations can greatly enhance your ability to build dynamic and responsive web applications. By following the steps outlined in this post, you can set up a PostgreSQL client, fetch data server-side, and handle errors gracefully, all while leveraging TypeScript for better type safety and developer experience.
Building data-driven applications has never been easier with Next.js 13 and its powerful new features. Dive in, explore more, and see how you can enhance your projects with server-side data fetching and database integration.