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.
useEffect
with an Async Function and Server ActionIn 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;
useEffect
with Route HandlersIn 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;
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.
useEffect
for data fetching in a client component, or should I strictly use Route handlers for this purpose?Any insights or recommendations would be greatly appreciated. Thank you!
What is the best practice for fetching data in a client component in Next.js 14?
route handlers with data fetching libraries, such as react-query or swr.
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?
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.
Are there any performance or architectural considerations I should be aware of when choosing between these methods?
server actions cannot be run in parallel, so that completely disqualifies them from being a good data querying method.