简体   繁体   中英

How do I specify an optional prop in the returned React$Element in Flow?

I have a React component that, based on which prop it receives, might return either a non-clickable div (ie, without an onClick -prop) or a clickable button (ie, with an onClick -prop). How do I specify this in the Flow type annotation?

I used to use ?React$Element<*> as the return type, but that didn't work, so I simply tried replacing * with an object, specifying the types. ?React$Element<{ className: string }> worked just fine, but I can't seem to add an optional onClick . I've tried both onClick?: Function - a syntax I've seen in some places - and onClick: ?Function - as you see below - but both throw the error at the bottom.

type RequestDataButtonType = (props: Props) => ?React$Element<{
  className: string,
  onClick: ?Function,
}>

const RequestDataButton
  : RequestDataButtonType
  = ({ requestData, status }) => {
    if (status === Status.REQUESTED) {
      return (
        <div className={css.requested}>
          Contact details requested
        </div>
      )
    } else if (status === Status.ERROR) {
      return (
        <button
          className={css.error}
          onClick={requestData}>
          Error
        </button>
      )
    } else if (status === Status.REQUESTING) {
      return (
        <div className={css.requesting}>
          Requesting contact details
          <LoadIndicator className={css.loadIndicator} />
        </div>
      )
    } else {
      return (
        <button
          className={css.request}
          onClick={requestData}>
          Request contact details
        </button>
      )
    }
  }

Flow throws the following errors for the above code (ignore line numbers, I've removed some irrelevant code):

> flow; test $? -eq 0 -o $? -eq 2

src/content/components/RequestDataButton/RequestDataButton.js:43
 43:         <div className={css.requested}>
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ React element: `div`
 33: type RequestDataButtonType = (props: Props) => ?React$Element<{
                                                                   ^ property `onClick`. Property not found in
 43:         <div className={css.requested}>
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ props of JSX Intrinsic: `div`

src/content/components/RequestDataButton/RequestDataButton.js:57
 57:         <div className={css.requesting}>
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ React element: `div`
 33: type RequestDataButtonType = (props: Props) => ?React$Element<{
                                                                   ^ property `onClick`. Property not found in
 57:         <div className={css.requesting}>
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ props of JSX Intrinsic: `div`


Found 2 errors

You can use $Shape<T> to pass the typecheck.

This works:

type RequestDataButtonType = (props: Props) => ?React$Element<$Shape<{
  className: string,
  onClick: ?Function,
}>>

$Shape<T> doesn't require all properties to be defined, but the ones that are defined must match the type definition.

In other words, you're describing any ReactElement that can optionally have onClick , but - if it does - then it must be a ?Function .

Here's a fully working example (I replaced some of your types but the gist is there):

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM