React报错修复:传递lucide-react Icon时函数不可作为React子元素
修复React中"Functions are not valid as a React child"错误
错误原因
你的代码存在两个核心问题:
withIcon是高阶组件(HOC),作用是包装组件类/函数,但你传入的icon是已经实例化的React元素(比如<User2 />),并非组件本身。- 直接调用
withIcon(icon)返回的是一个组件函数,React无法直接渲染函数,必须渲染组件的实例(即<Component />形式)。
修复方案
方案1:直接修改已有Icon元素(推荐)
不需要使用高阶组件,通过React.cloneElement给传入的Icon元素添加样式,这是处理已有React元素的标准方式:
修改Input组件代码:
import { cn } from '@/lib/utils'; import React, { HtmlHTMLAttributes, cloneElement } from 'react'; interface CompType { icon?: React.ReactNode; } export default function Input({ className, icon, ...props }: HtmlHTMLAttributes<HTMLInputElement> & CompType) { return ( <div className='shadow-md hover:shadow-lg transition-all px-6 flex items-center h-14 text-4xl rounded-full overflow-hidden'> <input {...props} className={cn('outline-none grow', {}, className)} /> {/* 给传入的icon元素添加className */} {icon && cloneElement(icon, { className: 'text-blue-400' })} </div> ); }
Login组件代码无需修改,依然保持icon={<User2 />}即可。
方案2:保留高阶组件,调整传参方式
如果坚持使用withIcon高阶组件,需要调整传参逻辑,传入组件而非实例化元素:
- 修改Input组件的接口,让
icon接收组件类型:
interface CompType { icon?: React.ElementType; // 改为组件类型,不再是ReactNode }
- 修改Input组件中Icon的渲染逻辑:
import { cn } from '@/lib/utils'; import React, { HtmlHTMLAttributes } from 'react'; const withIcon = (OriginalComponent) => { return function NewComponent() { return <OriginalComponent className='text-blue-400' />; }; }; interface CompType { icon?: React.ElementType; } export default function Input({ className, icon, ...props }: HtmlHTMLAttributes<HTMLInputElement> & CompType) { // 用HOC包装组件,然后渲染实例 const IconComponent = icon ? withIcon(icon) : null; return ( <div className='shadow-md hover:shadow-lg transition-all px-6 flex items-center h-14 text-4xl rounded-full overflow-hidden'> <input {...props} className={cn('outline-none grow', {}, className)} /> {IconComponent && <IconComponent />} </div> ); }
- 调整Login组件的传参,传入组件本身:
import Input from '@/components/atoms/input'; import { User2 } from 'lucide-react'; export default function Login() { return ( <section className='container'> <Input placeholder='email' icon={User2} /> {/* 这里传User2组件,不是<User2 /> */} </section> ); }
内容的提问来源于stack exchange,提问作者sohanemon
相关产品推荐
相关产品推荐

