当通过组件作为道具时,我尝试渲染它时会出现TS2604错误

时间:2019-05-20 11:28:04

标签: reactjs typescript

我想将一个组件作为道具传递给另一个组件 我的想法是,我可以传递组件来包装模态的内容(来自材料ui),

这是我尝试过的

import React, { Component } from 'react';
import withWidth, { isWidthDown } from '@material-ui/core/withWidth';
import Button from '@material-ui/core/Button';
import MuiDialog from '@material-ui/core/Dialog';
import { Breakpoint } from "@material-ui/core/styles/createBreakpoints";
import DialogActions from '@material-ui/core/DialogActions';
import DialogContent from '@material-ui/core/DialogContent';
import DialogContentText from '@material-ui/core/DialogContentText';
import DialogTitle from '@material-ui/core/DialogTitle';
import ButtonSpinner from './ButtonSpinner';

interface OwnProps {
  title: string
  open: boolean
  content: React.ReactNode
  isRunning: boolean
  confirmText: string
  declineText: string
  innerWrapper?: React.ReactNode
  innerWrapperProps?: any
  contentWrapper?: React.ReactNode
  onClose(): void
  onConfirm(): void
  onDecline(): void
  width: Breakpoint;
}

const InnerWrapperDefault: React.ReactNode = (p: any) => (
  <React.Fragment {...p} />
);
const ContentWrapperDefault: React.ReactNode = (p: any) => (
  <DialogContent {...p} />
);

class Dialog extends Component<OwnProps> {
  renderContent = () => {
    const { content } = this.props;

    switch (typeof content) {
      case 'string':
        return <DialogContentText>{content}</DialogContentText>;
      case 'function':
        return content();
      default:
        return content;
    }
  }

  render() {
    const {
      title,
      content,
      children,
      onClose,
      onConfirm = null,
      onDecline = null,
      confirmText = 'Enig',
      declineText = 'Uenig',
      isRunning = false,
      width,
      innerWrapper: InnerWrapper = InnerWrapperDefault,
      innerWrapperProps = null,
      contentWrapper: ContentWrapper = ContentWrapperDefault,
      ...rest
    } = this.props;

    return (
      <MuiDialog
        fullScreen={isWidthDown('xs', width) ? true : undefined}
        onClose={onClose}
        disableBackdropClick={isRunning}
        disableEscapeKeyDown={isRunning}
        aria-labelledby="responsive-dialog-title"
        {...rest}
      >
        <InnerWrapper {...innerWrapperProps}>
          <DialogTitle id="responsive-dialog-title">{title}</DialogTitle>
          <ContentWrapper>
            {content && this.renderContent()}
            {children}
          </ContentWrapper>
          <DialogActions>
            <Button onClick={onDecline || onClose} color="primary" disabled={isRunning}>
              {declineText}
            </Button>
            {onConfirm &&
              <ButtonSpinner isRunning={isRunning}>
                <Button onClick={onConfirm} color="primary" autoFocus disabled={isRunning}>
                  {confirmText}
                </Button>
              </ButtonSpinner>
            }
          </DialogActions>
        </InnerWrapper>
      </MuiDialog>
    );
  }
}

export default withWidth()(Dialog);

当我尝试使用此Typescript时,InnerWrapper和ContentWrapper会引发错误

JSX元素类型'...'没有任何构造或调用签名。

有什么建议可以使我工作吗?

编辑:添加了通话示例 可以用这样的东西来调用

return (
<Dialog
        confirmText="Yes"
        declineText="No"
        title="Dialog title"
        content="Dialog content"
        innerWrapper: (p: any) => <React.Fragment {...p} />,
    />
)

1 个答案:

答案 0 :(得分:0)

我认为您的问题是,您正在尝试使用不存在的类型。

在分解道具时,您尝试分配innerWrappercontentWrapper的类型InnerWrapperContentWrapper

const {
  ...
  innerWrapper: InnerWrapper = DefaultInnerWrapper,
  contentWrapper: ContentWrapper = DefaultContentWrapper
  ...
} = this.props;

但是这些类型没有定义(例如,作为接口或从模块导入)。

如果您只是删除它们并解构道具,就可以了:

const {
  ...
  innerWrapper = DefaultInnerWrapper,
  contentWrapper = DefaultContentWrapper
  ...
} = this.props;

然后另一个问题是,您试图将它们呈现为组件:

<InnerWrapper {...innerWrapperProps}/>
  ...
  <ContentWrapper/>

意味着您尝试从非引用对象创建JSX元素。如果要渲染它们,则应为它们创建组件/功能。我认为您可以在道具中将innerWrapper重命名为InnerWrapper,将contentWrapper重命名为ContentWrapper,以将其用作组件。

编辑:因此,我了解了使用ES6销毁时的重命名。

但是要为您提供帮助:如已here所述,您应该使用React.ComponentType而不是React.ReactNode作为包装类型,以解决错误消息。