Flow: React ES6 failures

Created on 30 Mar 2016  路  9Comments  路  Source: facebook/flow

Can someone explain why this code:

/* @flow */
import React from 'react';// eslint-disable-line no-unused-vars

type Props = {
  receiver: string
};

type State = {
  value: number
};

class Test extends React.Component<void, Props, State> {

  constructor() {
    super();
    this.state = {
      value: 0
    }
  }

  render() {
    return (
      <div>Hello {this.props.receiver}: {this.state.value}</div>
    );

  }
}

export default Test;

fails with the following error?

src/components/Util/test.js:12
 12: class Test extends React.Component<void, Props, State> {
                                                     ^^^^^ object type. This type is incompatible with
 12: class Test extends React.Component<void, Props, State> {
                                                     ^^^^^ undefined. Did you forget to declare State?

src/components/Util/test.js:12
 12: class Test extends React.Component<void, Props, State> {
                                                     ^^^^^ undefined. Did you forget to declare State?. This type is incompatible with
 12: class Test extends React.Component<void, Props, State> {
                                                     ^^^^^ object type

I stripped everything from my code to come with this example. I can not understand why it doesn't pickup my definition of State.

react

Most helpful comment

I had the same issue but I solved it differently. If you really need your state to be in your constructor (for example if it depends on the props, or if you compiler doesn't compile class properties), you can add a type annotation for the State in the class:

class Playground extends Component<void, Props, State> {
  state: State; // <- There

  constructor() {
    super();
    this.state = {
      count: 0,
    };
  }

  ...
}

Then you won't get the error anymore.

All 9 comments

I've been trying to work through similar issues over at facebook/flux#336. I added a state property declaration with type annotation to the class along the lines of http://flowtype.org/docs/react.html#higher-order-components and it seemed to have fixed the error.

That is how I do it now as well, I just liked the 'generics way' better :-)

@hmeerlo It'd be nice to get the 'generics way' working too. I am assuming the State in extends Component<void, Props, State> should be enough for the type to be inferred if flow is picking up on https://github.com/facebook/flow/blob/master/lib/react.js#L16. But perhaps not if the $Abstract means the subclass needs to specify re: https://github.com/facebook/flow/blob/master/lib/react.js#L21.

I ran into a similar issue, and it turns out that currently you need to use the experimental stage-1 features to really work around this issue.

So your code, written like this would work correctly with flow.

/* @flow */
import React from 'react';// eslint-disable-line no-unused-vars

type Props = {
  receiver: string
};

type State = {
  value: number
};

class Test extends React.Component<void, Props, State> {
  state = {value: 0};

  render() {
    return (
      <div>Hello {this.props.receiver}: {this.state.value}</div>
    );

  }
}

export default Test;

The same is also true for default props. If you use Test.defaultProps = {} after the class definition, Flow complains. But if you put a static defaultProps = {}; inside the class body flow is fine with it.

Of course to use class static and property fields, you need to add this to your .flowconfig:

[options]
esproposal.class_static_fields=enable
esproposal.class_instance_fields=enable

I hope this problem can be fixed soon, but at least I have a proper work around for now.

Thanx, it seems to work. I do need to make one small change, I must annotate the state with its type, otherwise flow complains about a missing annotation:

state: State = {value: 0};

may or may not relate to #1908

I had the same issue but I solved it differently. If you really need your state to be in your constructor (for example if it depends on the props, or if you compiler doesn't compile class properties), you can add a type annotation for the State in the class:

class Playground extends Component<void, Props, State> {
  state: State; // <- There

  constructor() {
    super();
    this.state = {
      count: 0,
    };
  }

  ...
}

Then you won't get the error anymore.

Ok, Meet this issue and got fixed by @adriantoine 's solution. But it's a duplication, right ?

I think this issue can be closed. The original example, after just a tiny syntax change, now works fine in Flow v0.53, which improved the way Components are typed. (/cc @calebmer)

Was this page helpful?
0 / 5 - 0 ratings

Related issues

john-gold picture john-gold  路  3Comments

ghost picture ghost  路  3Comments

jamiebuilds picture jamiebuilds  路  3Comments

cubika picture cubika  路  3Comments

iamchenxin picture iamchenxin  路  3Comments