Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use Flow with React.createRef()?

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?

like image 822
Zardoz Avatar asked Apr 28 '18 11:04

Zardoz


People also ask

What is the use of createRef in React?

This method is used to access any DOM element in a component and it returns a mutable ref object which will be persisted as long as the component is placed in the DOM. If we pass a ref object to any DOM element, then the. current property to the corresponding DOM node elements will be added whenever the node changes.

Can I use createRef in functional component?

createRef can be used in both class and functional components.

Can I add ref to React component?

You can create a ref by calling React. createRef() and attaching a React element to it using the ref attribute on the element. We can “refer” to the node of the ref created in the render method with access to the current attribute of the ref. From the example above, that would be this.


4 Answers

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} />
    )
  }
}
like image 102
allienx Avatar answered Oct 21 '22 09:10

allienx


There is a related github issue.

If it's not fixed yet you can type it yourself:

type RefObject = {|
  current: any,
|};

This is how it is typed internally in react library type definitions.

like image 37
Tomasz Mularczyk Avatar answered Oct 21 '22 07:10

Tomasz Mularczyk


If you are using "class properties", you may createRef() in the following way:

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

export class TestComponent extends React.Component<{}> {
  myRef = React.createRef<HTMLElement>();

  render() {
    return (
      <div ref={this.myRef} />
    )
  }
}
like image 1
jmarceli Avatar answered Oct 21 '22 09:10

jmarceli


In my case I was using formik reference

// @flow
import React from 'react';
import { Formik } from "formik"


export class TestComponent extends React.Component<Props> {
   formikRef = React.createRef<Formik>();

  render() {
     return (
         <Formik 
            ...,
            ref={this.formikRef}
         />
     )
  }
}
like image 1
Umar Asghar Avatar answered Oct 21 '22 08:10

Umar Asghar