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

Next.js+TS构建静态页时报Array is not iterable错误

Next.js构建阶段「Array is not iterable」错误修复

问题现象

使用TypeScript开发Next.js应用时,开发环境开启严格类型检查无任何报错,自定义Accordion组件接收accordion对象数组props时运行正常,但执行生产构建的静态页面生成环节时,抛出Array is not iterable错误。
相关组件代码如下:

import React from 'react'
import Link from 'next/link'
import { nanoid } from 'nanoid'
import { NextPage } from 'next'

interface Section {
  header: string
  prompt: string
  linkRef: string
  linkTxt: string
  bs: string
  id: string
}
type Props = {
  accordion: Section[]
  children: any[]
}

const Accordion: NextPage<Props> = ({ accordion, children }) => {
  const [firstItem, ...otherItems] = accordion
  console.log(accordion)
  const others = otherItems.map((i: Section, index: number) => (
    <div key={nanoid()} className="accordion-item">
      <h2 className="accordion-header" id={`heading${i.bs}`}>
        <button
          className="accordion-button"
          type="button"
          data-bs-toggle="collapse"
          data-bs-target={`#collapse${i.bs}`}
          aria-expanded="true"
          aria-controls={`collapse${i.bs}`}
        >
          {i.header} →
        </button>
      </h2>
      <div
        id={`collapse${i.bs}`}
        className="accordion-collapse collapse"
        aria-labelledby={`heading${i.bs}`}
        data-bs-parent="#main"
      >
        <section id={i.id} className="accordion-body">
          <div>{children[index + 1]}</div>
          <div>
            {i.prompt}
            <Link href={i.linkRef}>
              <a>{i.linkTxt}</a>
            </Link>
          </div>
        </section>
      </div>
    </div>
  ))

  return (
    <div key={nanoid()} className="accordion" id="main">
      <div className="accordion-item">
        <h2 className="accordion-header" id="headingOne">
          <button
            className="accordion-button"
            type="button"
            data-bs-toggle="collapse"
            data-bs-target="#collapseOne"
            aria-expanded="true"
            aria-controls="collapseOne"
          >
            {firstItem.header} →
          </button>
        </h2>
        <div
          id="collapseOne"
          className="accordion-collapse collapse"
          aria-labelledby="headingOne"
          data-bs-parent="#main"
        >
          <section id={firstItem.id} className="accordion-body">
            <div className="mdxContainer">{children[0]}</div>
            <div>
              {firstItem.prompt}
              <Link href={firstItem.linkRef}>
                <a>{firstItem.linkTxt}</a>
              </Link>
            </div>
          </section>
        </div>
      </div>
      {others}
    </div>
  )
}

export default Accordion

已排查到的现象:

  • 开发环境运行完全正常,TS无类型报错
  • 报错仅出现在生产构建的静态生成阶段
  • 运行时日志打印accordion为数组类型,Array.isArray(accordion)返回true

根因分析

  1. 错误的组件类型标注是核心诱因:NextPage类型是Next.js为pages/目录下的路由页面组件专门设计的类型,构建阶段Next.js会对所有标记为NextPage的组件执行特殊的页面级props注入逻辑。在静态生成的首次预渲染 pass 中,框架会优先尝试读取页面级静态props(getStaticProps/getServerSideProps返回值),你手动传入的accordion props在这一步会被覆盖为undefined,执行数组解构时直接抛出不可迭代错误。
  2. 日志偏差导致排查方向错误:你看到的accordion为数组的日志,都是客户端hydration完成后的运行时打印,构建报错发生在服务端预渲染的最早阶段,代码还没执行到console.log就已经抛出错误中断构建,所以你看不到这次失败渲染的实际入参。
  3. 缺少容错逻辑放大问题:组件没有给数组类型props设置兜底默认值,TS静态类型检查无法覆盖构建阶段框架动态注入props的场景,一旦入参不符合预期就直接触发运行时错误。

修复步骤

按以下顺序修改即可解决构建报错:

  1. 移除错误的NextPage类型标注:普通可复用UI组件不要使用NextPage类型,直接标注props类型即可,同时删掉无用的NextPage导入。
  2. 给所有数组类型props添加空数组默认值,从根源避免解构时拿到非可迭代值:
    // 修改后的组件签名
    const Accordion = ({ accordion = [], children = [] }: Props) => {
      // 原有业务逻辑保持不变
    }
    
  3. 修正children类型定义:React children不永远是数组,单个子节点时为单个React元素,无传入时为undefined,将Props里的children类型从any[]改为内置的React.ReactNode,避免后续出现类型和运行时不匹配的问题。
  4. (可选优化)移除渲染时随机生成key的逻辑:不要在map循环和组件根节点调用nanoid()生成key,服务端渲染和客户端hydration时生成的随机id不一致会触发hydration mismatch警告,直接使用每个Section自带的唯一id字段作为key即可,组件根节点不需要额外加key。

内容的提问来源于stack exchange,提问作者Ryan Gregory

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 07:24:25