Consider this Next.js server component that fetches user data from a database and renders the user's name.
import { db } from '@/lib/db';
export default async function UserName() {
const user = await db.user.findFirst({ where: { id: 1 } });
return <h1>{user?.name ?? 'Guest'}</h1>;
}If the database has a user with id 1 and name 'Alice', what will this component render?
import { db } from '@/lib/db'; export default async function UserName() { const user = await db.user.findFirst({ where: { id: 1 } }); return <h1>{user?.name ?? 'Guest'}</h1>; }
Think about what happens when the user is found and when it is not.
The component uses optional chaining user?.name which safely accesses the name if user exists. Since the user with id 1 exists and has name 'Alice', it renders <h1>Alice</h1>.
Given this Next.js server component:
import { db } from '@/lib/db';
export default async function ProductList() {
const products = await db.product.findMany();
return (
<ul>
{products.map(p => <li key={p.id}>{p.name}</li>)}
</ul>
);
}What happens if the database query takes a long time?
import { db } from '@/lib/db'; export default async function ProductList() { const products = await db.product.findMany(); return ( <ul> {products.map(p => <li key={p.id}>{p.name}</li>)} </ul> ); }
Remember server components run on the server and can await data before rendering.
Server components in Next.js can use async/await to fetch data before rendering. The component waits for the database query to finish, then renders the list.
Look at this server component fetching data and rendering a count:
import { db } from '@/lib/db';
import { useState } from 'react';
export default async function Counter() {
const count = await db.count.findFirst();
const [value, setValue] = useState(count.value);
return (
<div>
<p>Count: {value}</p>
<button onClick={() => setValue(value + 1)}>Increment</button>
</div>
);
}Why does this cause a hydration error in Next.js?
import { db } from '@/lib/db'; import { useState } from 'react'; export default async function Counter() { const count = await db.count.findFirst(); const [value, setValue] = useState(count.value); return ( <div> <p>Count: {value}</p> <button onClick={() => setValue(value + 1)}>Increment</button> </div> ); }
Think about the difference between server and client components in Next.js.
React hooks like useState only work in client components. Server components run on the server and cannot use hooks. Using useState in a server component causes hydration errors.
Choose the correct syntax to fetch all posts from the database in a Next.js server component.
Remember that await can only be used inside async functions.
Option C correctly defines an async function and uses await to get posts before rendering. Options A, B, and C misuse await or async. Option C misses await in the async function.
In Next.js, why is it recommended to perform database queries inside server components rather than client components?
Think about security and where code runs in Next.js.
Server components run on the server, keeping database credentials safe and preventing exposure to the client. Client components run in the browser and should not contain sensitive code like database queries.