You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Next.js+React中axios响应无法存入state及网络错误排查

问题根因

你遇到的两个问题对应两个独立的逻辑错误,和请求头配置无关:

  • 组件顶层直接调用test()请求方法的问题
    React函数组件每次状态更新触发重渲染时,都会从头执行一遍整个函数体逻辑。你直接在函数顶层调用请求方法,会形成「发请求→setProducts更新状态→触发重渲染→重渲染又调用test()发请求」的死循环;同时setProducts是异步批更新逻辑,你在调用test()后同步打印products,拿到的永远是当次渲染闭包里的初始空数组,等不到状态更新后的结果。
  • 浏览器报ERR_NETWORK、服务端能正常拿到响应的问题
    你之前尝试的“开启CORS”操作完全无效:CORS规则是目标接口服务器通过响应头控制的,只有VTEX接口服务端配置了允许你的前端域名跨域访问,浏览器才会放行请求,你作为请求方在自己项目里配CORS头没有任何作用。服务端发请求不受浏览器同源策略限制,所以终端能正常拿到数据;浏览器直接请求VTEX域名时被跨域策略拦截,才会返回没有状态码的网络错误。
可行解决方案

优先选第一个方案,性能最好、逻辑最简单:

方案1:直接用Next.js服务端能力获取数据(推荐)

Next.js是全栈框架,数据请求直接放在服务端执行,彻底绕开浏览器跨域限制,不需要写useState、useEffect管理请求状态:

  • 如果你用App Router,直接写异步服务端组件即可,组件代码默认跑在服务端:
// app/products/page.jsx
import axios from 'axios'

export default async function ProductsPage() {
  // 服务端直接请求VTEX接口,不存在跨域问题,鉴权信息写在这里也不会泄露到前端
  const { data: products } = await axios.get('替换成你的VTEX商品搜索接口地址', {
    headers: {
      Accept: 'application/json'
    }
  })

  return (
    <div className="product-list">
      {products.map(product => (
        <div key={product.productId}>{product.productName}</div>
      ))}
    </div>
  )
}
  • 如果你用Pages Router,用getServerSideProps在服务端预取数据,再把数据作为props传给页面组件渲染即可。

方案2:写Next.js路由代理(必须客户端动态请求时用)

如果你的业务需要在客户端交互时动态拉取商品数据,就在Next.js里写一层同域名接口代理,浏览器只请求自己站点的接口,由Next.js服务端转发请求给VTEX,绕开跨域限制:

  1. 新建代理路由文件app/api/vtex-products/route.js:
import axios from 'axios'

export async function GET() {
  try {
    const { data } = await axios.get('替换成你的VTEX商品搜索接口地址', {
      headers: {
        Accept: 'application/json'
      }
    })
    return Response.json(data)
  } catch (err) {
    return Response.json({ msg: '请求失败' }, { status: 500 })
  }
}
  1. 在客户端组件中请求本地代理接口,注意请求逻辑必须放在useEffect中,空依赖数组保证只在组件挂载时执行一次:
'use client'
import { useState, useEffect } from 'react'
import axios from 'axios'

export default function ProductList() {
  const [products, setProducts] = useState([])
  const [loading, setLoading] = useState(true)

  useEffect(() => {
    const fetchData = async () => {
      try {
        // 请求同域名接口,无跨域问题
        const { data } = await axios.get('/api/vtex-products')
        setProducts(data)
      } catch (err) {
        console.error(err)
      } finally {
        setLoading(false)
      }
    }
    fetchData()
  }, [])

  if (loading) return <div>商品加载中</div>
  return (
    <div className="product-list">
      {products.map(product => (
        <div key={product.productId}>{product.productName}</div>
      ))}
    </div>
  )
}
避坑提示
  • 所有请求、定时器这类副作用逻辑,不要直接写在组件函数顶层,必须放在useEffect里或者绑定到用户交互事件(比如点击、输入事件)上,否则会触发无限重渲染。
  • 涉及第三方接口鉴权的密钥、token,一律放在服务端代码里,不要写在客户端请求逻辑中,避免泄露给用户。
  • 排查跨域问题时,先确认是浏览器端请求还是服务端请求,服务端请求不存在跨域限制,不需要做任何CORS配置。

内容的提问来源于stack exchange,提问作者pe.Math

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 07:06:07