Skip to content

Commit f0731d3

Browse files
authored
docs(blog): update next post (#6237)
1 parent 20910b5 commit f0731d3

File tree

1 file changed

+192
-1
lines changed

1 file changed

+192
-1
lines changed

documentation/blog/2023-05-29-next-js-server-actions.md renamed to documentation/blog/2024-08-07-next-js-server-actions.md

Lines changed: 192 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,12 @@ description: We'll delve into the Next.js alpha feature Server actions and data
44
slug: next-js-server-actions-and-data-fetching
55
authors: victor_uma
66
tags: [nextjs]
7-
image: https://refine.ams3.cdn.digitaloceanspaces.com/blog/2023-05-29-next-js-server-actions/social.png
7+
image: https://refine.ams3.cdn.digitaloceanspaces.com/blog/2023-05-29-next-js-server-actions/social-2.png
88
hide_table_of_contents: false
99
---
1010

11+
**This article was last updated on August 07, 2024, to add sections on Security Considerations and SWR.**
12+
1113
## Overview
1214

1315
Delivering flawless user experience and structured data retrieval is of the most important when it comes to web development. Next.js, a robust React framework, has become the go-to choice for developers seeking to optimize server-side rendering (SSR) and client-side rendering (CSR) capabilities. One crucial aspect that sets Next.js apart is its comprehensive toolkit for data fetching and server actions.
@@ -291,6 +293,195 @@ In the code above, we define a component `MyComponent` that fetches users from t
291293
Note that when making requests to API routes from the client-side code, you can use relative URLs like `/api/users` since Next.js automatically routes requests to the appropriate API route.
292294
Next.js API routes provide a powerful mechanism to handle server actions seamlessly within your application. Whether you need to fetch data, perform data mutations, or handle authentication, API routes enable you to define custom server endpoints with ease.
293295

296+
## Bonus: Securing API Routes in Our Next.js App
297+
298+
Just wanted to share some key practices in making sure our Next.js application is secure, especially with regard to the server actions and API routes.
299+
300+
### Protecting API Endpoints
301+
302+
First, we need to ensure that API routes are kept safe from unauthorized access. Here's what we can do:
303+
304+
#### JWT Authentication
305+
306+
We could authenticate users through JSON Web Tokens (JWT). When a user logs in, we will issue a token for them to send along with their requests.
307+
308+
```tsx
309+
import jwt from "jsonwebtoken";
310+
311+
export default function handler(req, res) {
312+
const { method } = req;
313+
if (method === "POST") {
314+
const { username, password } = req.body;
315+
// Verify user credentials
316+
if (username === "user" && password === "pass") {
317+
const token = jwt.sign({ username }, process.env.JWT_SECRET, {
318+
expiresIn: "1h",
319+
});
320+
res.status(200).json({ token });
321+
} else {
322+
res.status(401).json({ message: "Invalid credentials" });
323+
}
324+
} else {
325+
res.setHeader("Allow", ["POST"]);
326+
res.status(405).end(`Method ${method} Not Allowed`);
327+
}
328+
}
329+
```
330+
331+
#### Authorization Middleware
332+
333+
We will write a middleware that will check these tokens before giving access to any of our routes.
334+
335+
```tsx
336+
import jwt from "jsonwebtoken";
337+
338+
export default function handler(req, res) {
339+
const { authorization } = req.headers;
340+
if (!authorization) {
341+
return res.status(401).json({ message: "Authorization header missing" });
342+
}
343+
344+
const token = authorization.split(" ")[1];
345+
try {
346+
const decoded = jwt.verify(token, process.env.JWT_SECRET);
347+
req.user = decoded;
348+
// Proceed with the request
349+
} catch (error) {
350+
return res.status(401).json({ message: "Invalid token" });
351+
}
352+
}
353+
```
354+
355+
### Data Validation and Sanitization
356+
357+
Next, it's very important to validate and sanitize incoming data so that security risks like SQL injection or XSS attacks are avoided.
358+
359+
#### Validation of Data with Yup
360+
361+
The data validation can be done with the help of libraries like Yup to check for the desired type of data.
362+
363+
```tsx
364+
import { object, string } from "yup";
365+
366+
const schema = object({
367+
username: string().required().min(3).max(50),
368+
password: string().required().min(6),
369+
});
370+
371+
export default async function handler(req, res) {
372+
try {
373+
await schema.validate(req.body);
374+
// Process the validated data
375+
res.status(200).json({ message: "Data is valid" });
376+
} catch (error) {
377+
res.status(400).json({ message: error.message });
378+
}
379+
}
380+
```
381+
382+
#### Sanitizing Data
383+
384+
We should also sanitize user inputs so as to exclude all injurious content.
385+
386+
```tsx
387+
import { sanitize } from "dompurify";
388+
389+
export default function handler(req, res) {
390+
const { username, password } = req.body;
391+
const sanitizedUsername = sanitize(username);
392+
const sanitizedPassword = sanitize(password);
393+
394+
// Use sanitized data
395+
res.status(200).json({ message: "Data sanitized" });
396+
}
397+
```
398+
399+
## Bonus: Using SWR to Fetch Data Efficiently with Next.js
400+
401+
This will be the time when I will introduce you to one of the greatest data-fetching tools for our Next.js projects: SWR. Using SWR, we manage data fetching efficiently, ensuring that the UI stays fast and responsive while new data is fetched.
402+
403+
### SWR (Stale-While-Revalidate)
404+
405+
#### Introduction to SWR
406+
407+
SWR is a React Hooks library for remote data fetching. When working with this library, fetching data can be made really simple and assured that it is up-to-date with live data at any time. The acronym SWR stands for "Stale-While-Revalidate": a strategy in which the component exhibits stale data while it continues to revalidate in the background.
408+
409+
#### SWR for Data Fetching
410+
411+
Below is a simple example of how we might use SWR in our components.
412+
413+
```javascript
414+
import useSWR from "swr";
415+
416+
const fetcher = (url) => fetch(url).then((res) => res.json());
417+
418+
function MyComponent() {
419+
const { data, error } = useSWR("/api/data", fetcher);
420+
421+
if (error) return <div>Failed to load data</div>;
422+
if (!data) return <div>Loading...</div>;
423+
424+
return (
425+
<div>
426+
<p>{data.message}</p>
427+
</div>
428+
);
429+
}
430+
```
431+
432+
Here the function of `useSWR` is to take a key (the URL to fetch) and a fetcher function: it will automatically handle the fetch, error, and revalidation process.
433+
434+
#### Fetch User Data
435+
436+
```javascript
437+
import useSWR from "swr";
438+
439+
const fetcher = (url) => fetch(url).then((res) => res.json());
440+
441+
function UserProfile() {
442+
const { data, error } = useSWR("/api/user", fetcher);
443+
444+
if (error) return <div>Failed to load user data</div>;
445+
if (!data) return <div>Loading user data...</div>;
446+
447+
return (
448+
<div>
449+
<h1>{data.name}</h1>
450+
<p>{data.email}</p>
451+
</div>
452+
);
453+
}
454+
```
455+
456+
#### Managing Pagination
457+
458+
```javascript
459+
import useSWR from "swr";
460+
461+
const fetcher = (url) => fetch(url).then((res) => res.json());
462+
463+
const PaginatedList = ({ page }) => {
464+
const { data, error } = useSWR(`/api/items?page=${page}`, fetcher);
465+
466+
if (error) return <div>Failed to load items</div>;
467+
if (!data) return <div>Loading items...</div>;
468+
469+
return (
470+
<ul>
471+
{data.items.map((item) => (
472+
<li key={item.id}>{item.name}</li>
473+
))}
474+
</ul>
475+
);
476+
};
477+
```
478+
479+
#### Benefits of SWR
480+
481+
- **Automatic Caching and Revalidation**: SWR, in the background, caches the data and automatically revalidates it, making the UI fast, live, and always updated.
482+
- **Simple focus**: Abstract away fetching data; make our code more clean and maintainable.
483+
- **Error Handling**: SWR has error handling built-in, so it's fairly trivial to deal with data fetching failures.
484+
294485
## Conclusion
295486

296487
We explored the basics of Next.js, simplified setup process, and advantages. We delved into data fetching, showcasing both client-side and server-side techniques with code examples. Additionally, we explored the concept of server actions using Next.js API routes, enabling custom server endpoints for handling server-side logic and operations.

0 commit comments

Comments
 (0)