【问题标题】:How to fetch API data from Axios inside the getServerSideProps function in NextJS?如何在 NextJS 的 getServerSideProps 函数中从 Axios 获取 API 数据?
【发布时间】:2021-04-22 22:09:17
【问题描述】:

我正在使用 Next.js 构建一个应用程序,我需要连接到特定的 API 路由(使用 API Platform 设置)并使用路由的响应填充页面。

API 工作正常,但无论我如何尝试在 getServerSideProps 中实现我的 Axios 调用,我总是从我的节点堆栈中收到相同的错误 ECONNREFUSED

我尝试从useEffect() 获取数据并且工作正常,但我想知道是否有办法直接在getServerSideProps 中调用它。

我正在为 Docker 使用 Node 容器,并且路由通过 JWT 令牌(存储在会话和服务器端连接的客户端 cookie 中)进行身份验证

这是我的代码:

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 包装器:

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;

通过节点堆栈中的错误转储,我设法看到请求标头是正确的,并且 JWT 正确通过。

【问题讨论】:

  • URL 的其余部分是否添加到某处?相对 URL 在服务器上不起作用,因为它不像浏览器那样知道自己所在的域。
  • 嗨!我添加了一个 .env.local 文件来指定 API URL(使用 process.env.NEXT_PUBLIC_API_URL)。它指定 NEXT_PUBLIC_API_URL=localhost:8001 并且我可以在节点容器的错误堆栈中看到 url 是正确的......我还尝试直接在 getServerSideProps 中执行 axios 调用,使用完整的 url 字符串,仍然是相同的结果。 . 你建议我不这样做吗?谢谢!
  • 只要获取完整的 URL,我没有其他建议。这只是值得检查的事情。我在你现在提供的代码中看到了那部分,所以那是我的错误。
  • getStaticProps's context 无权访问req(也无标头/cookies),因为它在构建时在服务器上运行。您是否尝试过改用getServerSideProps
  • 嗨!是的,我很抱歉,我在帖子中放错了功能。我最初尝试使用 getServerSideProps 进行工作,我将立即编辑我的帖子。要回答您的问题,与 getServerSideProps 相同的问题

标签: reactjs api axios next.js


【解决方案1】:

不要使用 Axios。只需使用fetch()

Next.js 在客户端和服务器上默认填充 fetch(),所以你可以直接使用它:

除了客户端的 fetch() 之外,Next.js 在 Node.js 环境中填充 fetch()。您可以在服务器代码中使用fetch()(例如getStaticProps/getServerSideProps),而无需使用诸如isomorphic-unfetchnode-fetch 之类的polyfill。

Source.

【讨论】:

    【解决方案2】:

    你的问题是你的异步方法没有返回一个承诺。

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

    【讨论】:

      【解决方案3】:

      在将jwtToken 传递给服务后,您没有将其用于任何事情。

      const instance = axios.create(options); 行之前添加如下内容:

      if (jwtToken !== null) {
        options.headers.Authorization = `Bearer ${jwtToken}`
      }
      

      【讨论】:

        【解决方案4】:

        在我的 NextJS 开始时,我关注 this tutorial ,并以这种方式将 fetch 更改为 axios:

        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 },
           };
        };
        

        我使用 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);
          }, []);
        

        希望这些信息对你有用。

        【讨论】:

          猜你喜欢
          • 2021-09-04
          • 2023-02-18
          • 1970-01-01
          • 2021-12-30
          • 2021-12-31
          • 2022-01-26
          • 1970-01-01
          • 2020-07-25
          • 1970-01-01
          相关资源
          最近更新 更多