typescript报错:类型“ReactNode”的参数不能赋给类型“ReactElement<any, string

百科知识2025-04-273

最近在做antd项目,使用typescript写layout组件,通过cloneElement给子组件的props添加initialState中的数据遇到飘红:

类型“ReactNode”的参数不能赋给类型“ReactElement<any, string | JSXElementConstructor>”的参数。

这里涉及到下面两个知识点:

ReactNode

这是一种联合类型,可以是string、number、ReactElement、{}、boolean、ReactNodeArray。 是render的返回值,可以理解为展示到页面上的节点内容。

ReactElement

这是一种包含type、props、key这3种属性的对象。 type:组件的类型 props:组件的参数 key:组件的各种属性键值对 可以理解为虚拟dom里的组件,不能直接展示到页面上。

解决飘红很简单,将ReactNode类型转成ReactElement就行,代码如下:

{cloneElement(<>{children}</>, { ...currentUser, refresh })}

即将ReactNode用空节点包住,即可将ReactNode转成ReactElement。 但是又遇到了新的问题,这样children节点收不到props。

以上问题已有解决方法。 注意,使用umi框架的,可以通过定义里的layout来解决。

启用layout

编辑@/config/文件,启用layout:

layout: {<!-- -->
    // /zh-CN/plugins/plugin-layout
    ...defaultSettings,
  },

编辑
import type { RunTimeLayoutConfig } from 'umi' // 必须启用layouut插件才能导入
import { cloneElement } from 'react'

// ProLayout 支持的api /components/layout
export const layout: RunTimeLayoutConfig = ({ initialState, setInitialState }) => {

return {<!-- -->
    rightContentRender: () => <RightContent setInitialState={<!-- -->setInitialState} />,
    footerRender: () => <Footer />,
    disableContentMargin: false,
    onPageChange: () => {<!-- -->
        // 如果没有登录,重定向到 login
        if (initialState == null) {<!-- -->
            history.push('/user/login')
        }
    },
    childrenRender: (children) => {<!-- -->
        if (!initialState || (!initialState.currentUser && history.location.pathname !== loginPath))
            return <PageLoading />  // 初始状态为空 或 初始状态中当前用户为空且当前路径不是登录路径,那么返回空页面!
        return (
            <>
                {<!-- -->cloneElement(children, {<!-- --> ...initialState.currentUser })}
            </>
        )
    },
    ...initialState?.settings,
};

};

在这里写cloneElement,这里收到的children是类型,传给cloneElement不会飘红。 在这里可以将initialState中的数据传给各个页面组件。这样就不需要在各个页面组件中去用useModel(’@@initialState’)去获取初始数据。 但是需要提醒的是,一级路由下的页面可以正常收到初始数据,但二级路由下的页面不能收到,因为二级路由页面外面包了一层switch。 在umi官网中有关内容“传参数给子路由”,按照里面的方法并不能解决问题。