React Component Flow Union Types错误令人困惑

时间:2018-07-29 05:15:46

标签: reactjs flowtype union-types

我有一个按钮组件,可以拥有两种类型(联合类型)之一,但我不明白为什么Flow很难确定它是哪种类型。每条错误消息-我将在何处以及如何在“ tagType”中添加批注...我的意思是,我还没有在react组件中完成此操作吗?

类型:

type tPropsCommon = {
  children: React.Node,
  baseColor: string,
  textColor: string,
  inverse?: boolean,
  inverseStyle?: 'default' | 'transparent',
  hoverEffect?: 'default' | 'ripple',
  hoverBaseColor?: string,
  styles?: string, // emotion css string
  input?: {
    type: string,
  },
  onFileChange?: (
    event: SyntheticEvent<HTMLInputElement>,
    fileContents: string,
  ) => any,
}

export type tButton = {
  ...tPropsCommon,
  tagType: 'Link' | 'a' | 'button',
}

export type tButtonInput = {
  ...tPropsCommon,
  tagType: 'input',
  input: {
    type: 'button' | 'submit' | 'file',
  },
  onFileChange?: (
    event: SyntheticEvent<HTMLInputElement>,
    fileContents: string,
  ) => any,
}

组件:

export class Button extends React.Component<tButton | tButtonInput> {
  defaults = {
    hoverEffect: 'default',
    inverse: false,
    inverseStyle: 'default',
  }
  handleInputChange = async (event: SyntheticEvent<HTMLInputElement>) => {
    event.persist()
    if (event.currentTarget.files.length) {
      try {
        const fileContents: string = await readUploadedFileAsText(
          event.currentTarget.files[0],
        )
        if (this.props.onFileChange) {
          this.props.onFileChange(event, fileContents)
        } else {
          console.error(
            'You must provide an onFileChange prop when using an `input` button with a type of `file`',
          )
        }
      } catch (e) {
        console.warn(e.message)
      }
    }
  }
  render() {
    const {
      tagType,
      baseColor,
      textColor,
      inverse,
      inverseStyle,
      hoverEffect,
      hoverBaseColor,
      styles,
      children,
      ...props
    } = this.props

    const buttonProps = {
      'data-testid': 'component-button',
      options: {
        ...this.defaults,
        baseColor,
        textColor,
        inverse,
        inverseStyle,
        hoverEffect,
        hoverBaseColor,
        styles,
      },
    }

    switch (tagType) {
      case 'a':
        return (
          <A {...buttonProps} {...props}>
            {children}
          </A>
        )
      case 'button':
        return (
          <ButtonStyled {...buttonProps} {...props}>
            {children}
          </ButtonStyled>
        )
      case 'input':
        const { input, onFileChange, ...inputAttrs } = props
        if (input && input.type && input.type === 'file') {
          return (
            <Input {...buttonProps} {...inputAttrs}>
              <input
                onChange={this.handleInputChange}
                data-testid="component-button-input"
                {...input}
              />
              <span>{children}</span>
            </Input>
          )
        } else {
          return (
            <Input {...buttonProps} {...inputAttrs}>
              <input data-testid="component-button-input" {...input} />
              <span>{children}</span>
            </Input>
          )
        }
      case 'Link':
      default:
        return (
          <Link {...buttonProps} {...props}>
            {children}
          </Link>
        )
    }
  }
}

调用组件:

<Button
        {...{
          ...common,
          tagType: 'input',
          onFileChange: (event, fileContents) =>
            console.log(event,fileContents),
          input: {
            type: 'file',
          },
        }}
      >
        File Upload
      </Button>

流程错误:

Could not decide which case to select. Since case 1 [1] may work but if it
doesn't case 2 [2] looks promising too. To fix add a type annotation to
.input [3], to .onFileChange [3], or to .tagType [3].

        components/Button/stories.js
        67│   ))
        68│   .add('File upload', () => (
        69│     <Center>
    [3] 70│       <Button
        71│         {...{
        72│           ...common,
        73│           tagType: 'input',
        74│           onFileChange: (event, fileContents) =>
        75│             console.log(
        76│               '---event---\n',
        77│               event,
        78│               '\n---fileContents---\n',
        79│               fileContents,
        80│             ),
        81│           input: {
        82│             type: 'file',
        83│           },
        84│         }}
        85│       >
        86│         File Upload
        87│       </Button>
        88│     </Center>
        89│   ))
        90│   .add('With ripple hover effect', () => (

0 个答案:

没有答案