Published on

Resolving ECONNREFUSED Error in ShadCN DataTable with Axios in Next.js

Authors
  • Name
    Ripal & Zalak
    Twitter

When working with ShadCN UI DataTable in a Next.js application, you might encounter the following error while fetching data with Axios:

Error: connect ECONNREFUSED ::1:80

This error occurs when Axios cannot resolve the correct hostname for the API call. In this blog, we'll discuss the issue, its root cause, and how to resolve it effectively.


The Problem

You have a Next.js page component making a server-side call to an API using Axios:

async function getData(): Promise<Warga[]> {
  const res = await axios.get('/api/data')
  return res.data
}

However, this call results in the ECONNREFUSED error because Axios defaults to http://localhost/api/data, which is invalid in a server-side context.


Solution 1: Use the Full Hostname

To fix this issue, you need to provide the full hostname in the Axios request. This can be achieved by reading the host header in your server component. Here's how:

import { headers } from 'next/headers'
import axios from 'axios'

async function getData(): Promise<Warga[]> {
  const headersList = headers()
  const host = headersList.get('host') // Get the host from headers
  const res = await axios.get(`http://${host}/api/data`)
  return res.data
}

This approach dynamically constructs the API URL based on the server's hostname.


Solution 2: Direct Database Query in Server Component

Since your DataPage is a server component, you can eliminate the API route and fetch data directly from your Prisma database. This not only simplifies your architecture but also improves performance by reducing unnecessary HTTP calls.

Refactored getData Function

import { PrismaClient } from '@prisma/client'

const prisma = new PrismaClient()

async function getData(): Promise<Warga[]> {
  return await prisma.warga.findMany()
}

This approach bypasses the API route and directly queries the database.

Updated Page Component

import { DataTable } from './data-table'
import { columns } from './columns'

export default async function DataPage() {
  const data = await getData()
  return (
    <div className="container mx-auto my-8 flex-col md:flex">
      <div className="flex-1 space-y-4 pt-6 md:p-8">
        <DataTable columns={columns} data={data} />
      </div>
    </div>
  )
}

API Route Handler for Reference

If you want to retain the API route, here’s the corrected implementation:

import { NextResponse } from 'next/server'
import { PrismaClient } from '@prisma/client'

const prisma = new PrismaClient()

export const GET = async () => {
  const wargaData = await prisma.warga.findMany()
  return NextResponse.json(wargaData)
}

Key Takeaways

  1. Understand Server Context: Axios defaults to http://localhost for relative URLs, which can cause issues in server-side rendering.
  2. Eliminate Unnecessary Routes: If possible, directly query the database in server components to simplify your architecture.
  3. Use Dynamic Hosts: When necessary, construct the full API URL using the host header.

FAQs

Q: Why use the full hostname in the API call?
A: Server-side Axios requests don’t automatically resolve relative URLs. Providing the full hostname ensures that the request is correctly routed.

Q: Is it better to fetch data directly from Prisma?
A: Yes, if the component is server-side, directly querying Prisma is faster and avoids unnecessary HTTP requests.

Q: What if I still encounter connection errors?
A: Check your Prisma client configuration and ensure that the database is running and accessible.