typescript报错:类型“ReactNode”的参数不能赋给类型“ReactElement<any, string | JSXElementConstructor<any>>”的参数,如何解决?

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

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

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

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框架的,可以通过定义app.tsx里的layout来解决。

启用layout

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

    layout: {
        // https://umijs.org/zh-CN/plugins/plugin-layout
        ...defaultSettings,
      },

编辑app.tsx

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


// ProLayout 支持的api https://procomponents.ant.design/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是JSX.Element类型,传给cloneElement不会飘红。
在这里可以将initialState中的数据传给各个页面组件。这样就不需要在各个页面组件中去用useModel(’@@initialState’)去获取初始数据。
但是需要提醒的是,一级路由下的页面可以正常收到初始数据,但二级路由下的页面不能收到,因为二级路由页面外面包了一层switch。
在umi官网中有关内容“传参数给子路由”,按照里面的方法并不能解决问题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值