I’m working on a Next.js 14 project and I need to fetch data in a client component. I’ve come across two different methods and I’m unsure which one is the best practice.
Method 1: useEffect
with an Async Function and Server Action
In this method, I use useEffect
with an async function to fetch data directly from a server action that I also use in my server components. This way, I can reuse my server actions for both fetching and mutating data.
import React, { useEffect, useState } from 'react';
import { fetchIngresosForMonth } from './ServerActions'; // Server action
const ClientComponent = () => {
const [data, setData] = useState<ExtendedIngresosRow[]>([]);
useEffect(() => {
async function fetchData() {
try {
const fetchedData = await fetchIngresosForMonth();
console.log("Fetched data SERVER ACTION INGRESOS:", fetchedData);
setData(fetchedData);
} catch (error) {
console.error("Error fetching data SERVER ACTION INGRESOS:", error);
}
}
fetchData();
}, []);
return (
<div>
{/* Render data */}
</div>
);
};
export default ClientComponent;
Method 2: useEffect
with Route Handlers
In this method, I set up an API route using a Route handler and fetch the data within useEffect
by making a call to this route. According to the Next.js documentation, this seems to be the recommended way for fetching data in client components.
import React, { useEffect, useState } from 'react';
const ClientComponent = () => {
const [data, setData] = useState<ExtendedIngresosRow[]>([]);
useEffect(() => {
fetch('/api/IngresosRoutes/getIngresosDelMes')
.then(response => {
if (!response.ok) {
throw new Error('Network response was not ok');
}
return response.json();
})
.then(result => {
console.log("Fetched data:", result.resultOk);
setData(result.resultOk);
})
.catch(error => {
console.error("Error fetching data:", error);
});
}, []);
return (
<div>
{/* Render data */}
</div>
);
};
export default ClientComponent;
My Question
I prefer using the first method because it allows me to reuse server actions for both fetching and mutating data. However, the Next.js documentation states that server actions are primarily for mutating data and not for fetching data in client components. It also recommends using Route handlers for fetching data.
- What is the best practice for fetching data in a client component in Next.js 14?
- Is it acceptable to use server actions within
useEffect
for data fetching in a client component, or should I strictly use Route handlers for this purpose? - Are there any performance or architectural considerations I should be aware of when choosing between these methods?
Any insights or recommendations would be greatly appreciated. Thank you!
2
Answers
By: joulev
route handlers with data fetching libraries, such as react-query or swr.
no, see below. it's best to use data fetching libraries, but if you really want you can still use
useEffect
– but route handlers are required. why? see below.server actions cannot be run in parallel, so that completely disqualifies them from being a good data querying method.
https://youtu.be/RadgkoJrhu0?si=k6J9iouFOFj0gfyE
https://youtu.be/Qo_lxOI9GZU?si=1SefcDclF0GB_UTY
https://youtu.be/vrR4MlB7nBI?si=3lbgtee_PsSrQ26A
I suggest these videos to watch