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

Next.js13使用Render Props遇TypeError: children is not a function求助

问题:React 18/Next.js 13中Render Props报错“children is not a function”

首页代码

export default async function Home() {
  // console.log(data) it is populated
  const { data } = getAllArts();
  return (
    <main className="flex min-h-screen flex-col items-center justify-between p-24">
      <div className="z-10 max-w-5xl w-full items-center justify-between font-mono text-sm lg:flex">
        <ArtList arts={data}>
          {(art: Art) => <ArtCard key={art.id} art={art} disabled={false} />}
        </ArtList>
      </div>
    </main>
  );
}

ArtList组件代码(使用Render Props)

interface ArtListProps {
  arts: Art[];
  // using React.ReactNode causes type is not callable error
  children: FunctionComponent;
}

export default function ArtList({ arts, children }: ArtListProps) {
  return (
    <section className="grid md:grid-cols-1 lg:grid-cols-2 gap-4 mb-5">
      {arts.map((art) => children(art))}
    </section>
  );
}

报错信息

- error src/components/ui/art/ArtList.tsx (15:25) @ children
- error TypeError: children is not a function
    at eval (./src/components/ui/art/ArtList.tsx:12:35)
    at Array.map (<anonymous>)
    at ArtList (./src/components/ui/art/ArtList.tsx:12:24)
    at stringify (<anonymous>)

版本对比

  • 可正常运行版本:
    "next": "11.1.0",
    "react": "17.0.2",
    "react-dom": "17.0.2",
    
  • 当前使用版本:
    "next": "13.4.19",
    "react": "18.2.0",
    "react-dom": "18.2.0",
    

解决方法

问题根源是Next.js 13 App Router对children的处理逻辑变化,加上TypeScript类型定义错误,分两步修复:

  1. 修正TypeScript类型定义
    FunctionComponent是组件类型,不是渲染函数的正确类型。应该定义为接收Art参数并返回React节点的函数:
import type { ReactNode } from 'react';

interface ArtListProps {
  arts: Art[];
  children: (art: Art) => ReactNode;
}
  1. 适配App Router的children处理逻辑
    在Next.js 13 App Router中,传入组件的children会被自动包装为ReactNode(即使是函数),直接调用会报错。推荐两种解决方案:

方案一:用显式props传递渲染函数(更清晰安全)

修改组件调用方式,把渲染函数作为render props传入,而非children:

// 首页调用代码
<ArtList 
  arts={data} 
  render={(art: Art) => <ArtCard key={art.id} art={art} disabled={false} />} 
/>

// ArtList组件修改
interface ArtListProps {
  arts: Art[];
  render: (art: Art) => ReactNode;
}

export default function ArtList({ arts, render }: ArtListProps) {
  return (
    <section className="grid md:grid-cols-1 lg:grid-cols-2 gap-4 mb-5">
      {arts.map((art) => render(art))}
    </section>
  );
}

方案二:强制断言children为函数(仅兼容旧写法时用)

如果坚持用children传递函数,可通过类型断言绕过包装问题:

export default function ArtList({ arts, children }: ArtListProps) {
  const renderFn = children as (art: Art) => ReactNode;
  return (
    <section className="grid md:grid-cols-1 lg:grid-cols-2 gap-4 mb-5">
      {arts.map((art) => renderFn(art))}
    </section>
  );
}
  1. 额外验证
    确保getAllArts()返回的data是有效数组,避免因arts为undefined导致map执行出错。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 15:57:49