Arnauf
Arnauf

Reputation: 271

How to fetch API data from Axios inside the getServerSideProps function in NextJS?

I'm building an App with Next.js, and I need to connect to specific API routes (set up with API Platform) and populate pages with the route's responses.

The API is working fine, but no matter how I try to implement my Axios call inside the getServerSideProps, I always get the same error, ECONNREFUSED, from my Node stack.

I tried to get the data from useEffect() and it's working fine, but I would like to know if there's a way to call it directly in getServerSideProps.

I'm using a Node container for Docker, and the routes are authenticated through a JWT Token (stored in the session and the client cookies for the server-side connection)

Here are is my code:

pages/accounts.js:

export async function getServerSideProps(context) {
  const cookies = new Cookies(context.req.headers.cookie)
  const adminToken = cookies.get('jwtToken')

  const res = await getAllAccounts(adminToken)

  return {
    props: {
      testdata: ''
    },
  }
}

lib/accounts.js:

import service from '../service'

export const getAllAccounts = async (adminToken) => {
  const res = service({ jwtToken : adminToken }).get(`/accounts`).then((response) => {
  
  }).catch((error) => {
    console.dir(error)
  })
}

HTTP wrapper:

import axios from 'axios';
import jwt_decode from "jwt-decode";
import mockAdapter from 'axios-mock-adapter';

const service = ({ jwtToken = null, store = null, mockURL = null, mockResponse = null, multipart = false } = {}) => {
  const options = {};

  options.baseURL = process.env.NEXT_PUBLIC_API_URL + '/api';

  if(multipart === true) {
    options.headers = {
      'Content-Type': 'multipart/form-data'
    }
  } else {
    options.headers = {
      'Content-Type': 'application/ld+json',
      accept: 'application/ld+json'
    }
  }

  const instance = axios.create(options);

  instance.interceptors.response.use(response => {
    return response;
  }, error => {
    return Promise.reject(error);
  })

  if (mockURL !== null && mockResponse !== null) {
    let mock = new mockAdapter(instance);
    mock.onAny(mockURL).reply(200, mockResponse)
  }

  return instance;
};

export default service;

Through the error dump in the node stack, I managed to see that the request headers are correct, and the JWT correctly passed through.

Upvotes: 27

Views: 73369

Answers (5)

Titan7Web
Titan7Web

Reputation: 1

I Used Axios in getServerSideProps without any problems.

export const getServerSideProps: GetServerSideProps = async({
  params,
  res
}) => {
  try {
    const response = await axios.get(`/api/test`);
    return {
      props: {
        data: response.data
      },
    }
  } catch {
    res.statusCode = 404;
    return {
      props: {}
    };
  }
};

Upvotes: 0

Maxim
Maxim

Reputation: 183

getServerSideProps works well with axios if we return response.data

export const getServerSideProps: GetStaticProps = async ({ params }) => {
  const { brandName } = params as IParams;
  const brandData = await $host.get(`api/brand/${brandName}`).then(response => response.data);

  return {
    props: {
      brand: brandData,
    },
  };
};

Upvotes: 3

judlup
judlup

Reputation: 139

In my NextJS begining I followed this tutorial , and I changed fetch to axios in this way:

export const getStaticPaths = async () => {
   const res = await fetch('https://jsonplaceholder.typicode.com/users');
   const data = await res.json();

   const paths = data.map((ninja) => {
     return {
       params: { id: ninja.id.toString() },
     };
   });

   return {
     paths,
     fallback: false,
   };
};

export const getStaticProps = async (context) => {
   const id = context.params.id;
   const res = await fetch(`https://jsonplaceholder.typicode.com/users/${id}`);
   const data = await res.json();

   return {
     props: { ninja: data },
   };
};

I applied the change using useEffect()

useEffect(() => {
    // const data = await fetch(`https://jsonplaceholder.typicode.com/users/${id}`);
    // const res = await data.json();
    // setninja(res);
    const fetchData = async () => {
      const result = await axios(`https://jsonplaceholder.typicode.com/users/${id}`);

      setninja(result.data);
    };

    fetchData();
    console.log(data);
  }, []);

I hope this info will be useful for you.

Upvotes: 0

Asen Mitrev
Asen Mitrev

Reputation: 693

Your problem is that your async method does not return a promise.

import service from '../service'

export const getAllAccounts = async (adminToken) => {
  const res = service({ jwtToken : adminToken }).get(`/accounts`);
  return res;
}

Upvotes: 2

cobrexus
cobrexus

Reputation: 4806

Do not use Axios. Just use fetch().

Next.js polyfills fetch() by default on both the client and server, so you can just use it:

In addition to fetch() on the client-side, Next.js polyfills fetch() in the Node.js environment. You can use fetch() in your server code (such as getStaticProps/getServerSideProps) without using polyfills such as isomorphic-unfetch or node-fetch.

Source.

Upvotes: 11

Related Questions