sottar
sottar

Reputation: 161

how to define ref type by flowtype?

I trying to define type of ref by flowtype in react v16.4.0
But I couldn't resolve it, so please let me know how to define it.

these are sample code.
I want to know how to define ref of Props type.

Parents

export default class ParentComponent extends React.Component<Props, State> {
  constructor(props: Props) {
    super(props);
    ....
    this.listRef = createRef();
  }

  render() {
    return (
      <ChildComponent
        listRef={this.listRef}
      />
    );
  }
}

child

type Props = {
  listRef: Ref<>, // how to define here?
};

const ChildComponent = (props: Props) => {
  <div>
    <ul ref={props.listRef}>
    ...
    </ul>
    ...
  </div>
}

modules version

"react": "^16.4.0",
"flow-bin": "^0.73.0",

Upvotes: 10

Views: 10584

Answers (4)

Dominique PERETTI
Dominique PERETTI

Reputation: 1083

Using Flow 0.102, I get perfect typing with:

const componentRef = {| current: null | React.ElementRef<typeof MyComponent> |} } = React.createRef<MyComponent>()

Upvotes: 2

Andrew Smith
Andrew Smith

Reputation: 1444

I've now created a helper type for myself to abstract away the details:

// shared/types.js

export type ReactRefT<T> = { current: ?T }

// myComponent.jsx
class MyComponent extends React.Component {
  /* ... */
  myRef: ReactRef<SomeOtherComponent> = React.createRef()
}

Upvotes: 3

James Kraus
James Kraus

Reputation: 3478

Note from the future:

The type for createRef has changed, so this answer may be somewhat out-of-date. The type is now function createRef<T>(): {current: null | T}. Everything below is retained for reference.


Taking a look at the typedef for createRef(), we can see it returns an object with this type:

{current: null | React$ElementRef<ElementType>}

It would be a little verbose to include that every time we wanted to specify the result of createRef(), so let's make a helper type. The React$XXX types are supposed to be internal. So we'll use the React.XXX types instead:

type ReactObjRef<ElementType: React.ElementType> = 
  {current: null | React.ElementRef<ElementType>}

And then we'll use it like this:

(Try)

import * as React from 'react'

type ReactObjRef<ElementType: React.ElementType> = 
  {current: null | React.ElementRef<ElementType>}

type ParentProps = {}

class ParentComponent extends React.Component<ParentProps, null> {
  listRef: ReactObjRef<'ul'>

  constructor(props: ParentProps) {
    super(props);
    this.listRef = React.createRef();
  }

  render() {
    return (
      <ChildComponent
        listRef={this.listRef}
      />
    );
  }
}

type ChildProps = {
  listRef: ReactObjRef<'ul'>,
};

const ChildComponent = (props: ChildProps) => {
  const hoge = props.listRef.current;
  return (
    <div>
      <ul ref={props.listRef}>
      </ul>
    </div>
  )
}

Upvotes: 9

Daniel Steigerwald
Daniel Steigerwald

Reputation: 1101

Note it does not work for stateless functional components as described in Flow https://flow.org/en/docs/react/types/#toc-react-elementref

Beware it can happen with higher order components.

Upvotes: 0

Related Questions