我有一个按钮组件,可以拥有两种类型(联合类型)之一,但我不明白为什么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', () => (