typescript报错:类型“ReactNode”的参数不能赋给类型“ReactElement<any, string
最近在做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官网中有关内容“传参数给子路由”,按照里面的方法并不能解决问题。