Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cannot assign React.createRef() to this.[property] because inexact object type [1] is incompatible with exact RefObject #6378

Open
fterh opened this issue May 30, 2018 · 13 comments

Comments

@fterh
Copy link
Contributor

commented May 30, 2018

I understand that Flow doesn't presently support React.createRef() type definitions.

From React's source code, I found these:

export function createRef(): RefObject {
  const refObject = {
    current: null,
  };
  if (__DEV__) {
    Object.seal(refObject);
  }
  return refObject;
}
export type RefObject = {|
  current: any,
|};

I tried using this snippet in my code, but I get an error instead:

Cannot assign React.createRef() to this.[property] because inexact object type [1] is incompatible with exact RefObject [2].

@fterh

This comment has been minimized.

Copy link
Contributor Author

commented Jun 7, 2018

I've updated to the latest React and Flow versions, still getting these though!

@apsavin

This comment has been minimized.

Copy link
Contributor

commented Jun 11, 2018

Could you please reproduce it on flow.org/try

@fterh

This comment has been minimized.

Copy link
Contributor Author

commented Jun 11, 2018

I'm not sure how I can introduce React into the Try Flow environment, but I found a solution:

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

to:

export type RefObject = { current: any, };

By removing the pipelines/vertical bars, I no longer get the inexact object type is incompatible with exact RefObject error, although I don't quite understand why this happens, considering I copied and pasted the type definition.

@TrySound

This comment has been minimized.

Copy link
Collaborator

commented Jun 11, 2018

Did you read the end of that issue? createRef api is supported for a few last versions.
https://github.com/facebook/flow/blob/master/lib/react.js#L219

@apsavin

This comment has been minimized.

Copy link
Contributor

commented Jun 11, 2018

@fterh you can write import React from 'react' on Try Flow environment.

@fterh

This comment has been minimized.

Copy link
Contributor Author

commented Jun 11, 2018

@TrySound I did, which was why I mentioned that I have updated to the latest versions and confirmed that the error still occurs.

However, that was using my original code - I didn't see any updates in the Flow documentation - so thanks for linking me to the source code, I'll have a look when I can and see if I can figure it out.

@im-martijn

This comment has been minimized.

Copy link

commented Jul 26, 2018

It would be nice if the flow documentation for refs was updated. I tried typing a ref using the createRef API today, but couldn't get it to work.

I tried something like this:

type Ref = { current: null | HTMLElement };

export default class SomeClass extends React.Component<Props> {
	someRef: Ref;

	constructor(props: Props) {
		super(props);
		this.someRef = React.createRef();
	}

	render() {
		return (
			<Component ref={this.someRef} />
		);
	}
}

This gives me an error:
Cannot create Component element because a callable signature is missing in Ref [1] but exists in function type [2] in property ref.

Where [1] refers to the Ref type and [2] refers to the creatRef function type definition in flow.

So, what did I do wrong / should I do to fix this?

@TrySound

This comment has been minimized.

Copy link
Collaborator

commented Jul 26, 2018

@im-martijn Documenting every type definition is wasting of resources. Read actual definitions. They are quite clean and always in current state.
https://github.com/facebook/flow/blob/master/lib/react.js#L189

@im-martijn

This comment has been minimized.

Copy link

commented Jul 26, 2018

Yeah, I did look at that, but didn't get it completely. New to flow / typing in general.

declare type React$Ref<ElementType: React$ElementType> =
  | {current: React$ElementRef<ElementType> | null}
  | ((React$ElementRef<ElementType> | null) => mixed)
  | string;

This is how I decided to use: { current: null | HTMLElement }. I guess I'm not sure how to interpret React$ElementRef<ElementType>.

@TrySound

This comment has been minimized.

Copy link
Collaborator

commented Jul 26, 2018

React$Ref is global alias of

import * as React from 'react';
var a: React.Ref

same true for all react types.

@im-martijn

This comment has been minimized.

Copy link

commented Jul 26, 2018

Ah, great, thanks. I now have:

import * as React from 'react';
type Ref = { current: React.ElementRef<any> | null };

...and that seems to work.

But still: is this not outdated now? https://flow.org/en/docs/react/refs/

@Benjamin-Dobell

This comment has been minimized.

Copy link

commented Aug 21, 2018

The current flow type for Ref and createRef are incorrect, the type parameter is "specialized" as:

ElementType: React$ElementType

where we have React$ElementType:

declare type React$ElementType =
  | string
  | React$StatelessFunctionalComponent<any>
  | Class<React$Component<any, any>>;

This means Flow does not allow us to specify references to DOM elements (i.e. HTMLElement). This is incorrect as references to DOM elements is documented behavior, https://reactjs.org/docs/refs-and-the-dom.html

@Benjamin-Dobell

This comment has been minimized.

Copy link

commented Aug 21, 2018

My apologies, it's expected we type our Ref with a string literal, rather than an actual runtime type e.g.

We should use React.Ref<'div'> instead of React.Ref<HTMLDivElement>.

This seems a little odd to me, but works well enough once you realize.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
6 participants
You can’t perform that action at this time.