How to use Flow with React.createRef()?

Zardoz picture Zardoz · Apr 28, 2018 · Viewed 10.4k times · Source

Since React 16.3 it is possible to use React.createRef() to access a DOM element. I am also using Flow in my project, but the documentation still uses the old way.

The below code unfortunately fails:

/* @flow */
import * as React from 'react';

export class TestComponent extends React.Component<{}> {
  myRef: React.Ref<HTMLDivElement>

  constructor(props: any) {
    super(props)
    this.myRef = React.createRef()
  }

  render() {
    return (
      <div ref={this.myRef} />
    )
  }
}

with the following error:

Cannot instantiate `Ref` because in type argument `ElementType`:
 - Either a callable signature is missing in `HTMLDivElement` [1] but exists in
   `React.StatelessFunctionalComponent` [2].
 - Or `HTMLDivElement` [1] is incompatible with statics of `React.Component` [3].

How do I type it correctly?

Answer

allienx picture allienx · Jun 30, 2018

Looking at the flow type definition for React.createRef():

declare export function createRef<ElementType: React$ElementType>(
): {current: null | React$ElementRef<ElementType>};

I was able to do something like this:

/* @flow */
import * as React from 'react';

export class TestComponent extends React.Component<{}> {
  myRef: { current: null | HTMLDivElement }

  constructor(props: any) {
    super(props)
    this.myRef = React.createRef()
  }

  render() {
    return (
      <div ref={this.myRef} />
    )
  }
}