用打字稿反应-toastr 3

时间:2018-01-10 10:59:07

标签: javascript reactjs typescript

尝试在react / TS应用程序中使用react-toastr。但是提供的示例(https://tomchentw.github.io/react-toastr/)不起作用。

我像这样导入:

import { ToastContainer, ToastMessageAnimated } from "react-toastr";

并像这样使用:

class RegistrationSelectionPage extends React.Component<{}, {}> {

 public render() {
    let container: ToastContainer | null;

    return (
      <section className="RegistrationSelectionPage">
        <ToastContainer
          ref={ref => container = ref}
          className="toast-top-right"
          toastMessageFactory={ToastMessageAnimated}
        />
        <button onClick={() => container && container.warning('No connection', 'Error!')}>Click me</button>
...

我收到此错误:

Uncaught TypeError: Cannot call a class as a function
    at ./node_modules/babel-runtime/helpers/classCallCheck.js.exports.default 
...

我应该在ToastMessageAnimated上调用哪个函数?

请提供完整的工作示例,谢谢:)

1 个答案:

答案 0 :(得分:1)

@types不正确,看起来他们允许any toastMessageFactory道具来解决对正确类型的误解,导致各种混淆

从文档中可以看出React工厂函数https://tomchentw.github.io/react-toastr/#toastmessage

默认值为React.createFactory(ToastMessageAnimated),它是从lib中定义的Component类创建的工厂函数。这确实可以满足您当前的目的,但是当前的def会强制您指定它,并接受any,这完全违背了这一点,所以让我们看看修复defs

从默认值我们可以推导出toastMessageFactory应该是React.Factory<ToastMessageProps>的类型,它是来自具有基本ToastMessageProps的lib的一个组件类的工厂

查看源代码中的道具和组件(很高兴用Flow编写,这样就变得容易了)我们可以将@type/react-toastr defs改进为......

import { Component, ReactHTML, Factory, ReactNode } from 'react'

export interface ToastContainerProps {
  toastType?: IconClassNames
  id?: string
  preventDuplicates?: boolean
  toastMessageFactory?: Factory<ToastMessageProps>
  newestOnTop?: boolean
  onClick?: Function
}

export class ToastContainer extends Component<ToastContainerProps> {
    error: <P extends ToastMessageProps>(message: ReactNode, title: ReactNode, optionsOverride?: Partial<P>) => void
    info: <P extends ToastMessageProps>(message: ReactNode, title: ReactNode, optionsOverride?: Partial<P>) => void
    success: <P extends ToastMessageProps>(message: ReactNode, title: ReactNode, optionsOverride?: Partial<P>) => void
    warning: <P extends ToastMessageProps>(message: ReactNode, title: ReactNode, optionsOverride?: Partial<P>) => void
    clear: () => void
}

export interface IconClassNames {
    error: string
    info: string
    success: string
    warning: string
}

export interface ToastMessageProps {
    className?: string,
    type: string,
    iconClassNames?: IconClassNames,
    iconClassName?: string,
    closeButton?: boolean,
    onCloseClick?: Function,
    title?: any,
    titleClassName?: string,
    message?: any,
    messageClassName?: string
}

export interface ToastMessageAnimatedProps extends ToastMessageProps {
    className?: string,
    showAnimation?: string,
    hideAnimation?: string,
    timeOut?: number,
    extendedTimeOut?: number,
    tapToDismiss?: boolean,
    onRemove: Function,
    onClick?: Function,
    onCloseClick?: Function,
}

export interface ToastMessageQueryProps extends ToastMessageProps {
  style?: object,
  showMethod?: string,
  showDuration?: number,
  showEasing?: string,
  hideMethod?: string,
  hideDuration?: number,
  hideEasing?: string,
  timeOut?: number,
  extendedTimeOut?: number,
  tapToDismiss?: boolean,
  onRemove: Function,
  onClick?: Function,
  onCloseClick?: Function,
}

export class ToastMessageAnimated extends Component<ToastMessageAnimatedProps> {}
export class ToastMessageQuery extends Component<ToastMessageQueryProps> {}

您现在可以在自己的组件中正确使用这些...

import { 
  ToastContainer, 
  ToastMessageAnimated,
  ToastMessageAnimatedProps // import this too for stricter typing of factory
} from "react-toastr"

//... all exactly same as your example, except...

<ToastContainer ref={ref => container = ref}
                toastMessageFactory={React.createFactory<ToastMessageAnimatedProps>(ToastMessageAnimated)}
                />
<button onClick={() => container && container.warning<ToastMessageAnimatedProps>('No connection', 'Error!', {className: 'toast-top-right'})}>Click me</button>

此处我们还严格键入警告选项,并在其中设置className(这被设置为错误的容器道具,因此不会被应用)

现在,您还可以将JSX组件作为消息和标题传递

container.warning<ToastMessageAnimatedProps>(<div>No connection</div>, <h1>Error!</h1>, {className: 'toast-top-right'})