40

Flow is giving me the following error whenever I try to use this.state in my code:

object literal: This type is incompatible with undefined. Did you forget to declare type parameter State of identifier Component?:

Here is the offending code (though it happens elsewhere too):

class ExpandingCell extends Component {
    constructor(props) {
    super(props);
    this.state = {
        isExpanded: false
    };
}

Any help would be much appreciated =)

Nat Mote
  • 3,878
  • 13
  • 28
Michael Campsall
  • 4,135
  • 9
  • 32
  • 49

4 Answers4

60

You need to define a type for the state property in order to use it.

class ComponentA extends Component {
    state: {
        isExpanded: Boolean
    };
    constructor(props) {
        super(props);
        this.state = {
            isExpanded: false
        };
    }
}
Mohamed Elzarei
  • 489
  • 3
  • 18
edvinerikson
  • 679
  • 6
  • 2
  • That is indeed the answer, thanks! I am still unclear as to why the app was working despite this error... – Michael Campsall Apr 27 '16 at 04:23
  • The reason the app was working despite the error is because the app don't need it. Flow needs it to be able to do type checking correctly but not the actual app. – edvinerikson Apr 28 '16 at 14:46
  • 1
    It sure would be great if i could get flow to ignore that error then =) – Michael Campsall Apr 28 '16 at 21:11
  • 1
    @MichaelCampsall You can always disable flow altogether. It's a static type checker which helps you write expressive code, but it's totally optional for any kind of JS project (not only React Native). – Michał Szajbe May 31 '16 at 21:22
  • 1
    Rishat's edit on 23 Dec means that this answer now has invalid syntax. Someone with privileges please roll back. Type annotations in Flow use ':' – it should be `state: { isExpanded: Boolean; };` – Andy MacKinlay Feb 22 '17 at 02:32
  • giving me error on flow version 0.61.0, it wasn't before. – Nouman Tahir Feb 03 '18 at 18:57
  • This does not eliminate the flow error anymore, so there must have been some change. The Derek Soike solution eliminates the flow error. – arnoldbird Mar 12 '18 at 20:25
27

If you're using flow and want to set this.state in your component's constructor:


1. Create a type for this.state

type State = { width: number, height: number }

2. Initialize your component with that type

export default class MyComponent extends Component<Props, State> { ... }

3. Now you can set this.state without any flow errors

  constructor(props: any) {
    super(props)
    this.state = { width: 0, height: 0 }
  }

Here's a more complete example that updates this.state with the width and height of the component when onLayout is called.

// @flow

import React, {Component} from 'react'
import {View} from 'react-native'

type Props = {
  someNumber: number,
  someBool: boolean,
  someFxn: () => any,
}

type State = {
  width: number,
  height: number,
}

export default class MyComponent extends Component<Props, State> {

  constructor(props: any) {
    super(props)

    this.state = {
      width: 0,
      height: 0,
    }
  }

  render() {

    const onLayout = (event) => {
      const {x, y, width, height} = event.nativeEvent.layout
      this.setState({
        ...this.state,
        width: width,
        width: height,
      })
    }

    return (
      <View style={styles.container} onLayout={onLayout}>

        ...

      </View>
    )
  }
}

const styles = StyleSheet.create({
  container: {
    display: 'flex',
    flexDirection: 'column',
    justifyContent: 'center',
    alignItems: 'center',
  },
})
Derek Soike
  • 8,670
  • 1
  • 64
  • 67
  • How to utilize the type definition of `Props`? – Felix Jan 18 '18 at 08:44
  • This works, but I don't know why it's necessary to pass in Props as a type. The three properties in Props aren't actually used in the code sample. However, if I eliminate the Props type, this code then does not eliminate the flow error referenced in the original post. – arnoldbird Mar 12 '18 at 20:32
  • This worked for whereas the older answer on this question did NOT. – etayluz Mar 14 '18 at 20:07
  • @amoldbird ..would u able to find out the explanation ?? – Manish Mar 28 '18 at 07:42
0

You can ignore the state with flow type :any, but this is not recommended. You will get lost when your state get bigger and more complicated.

class ExpandingCell extends Component {

    state: any;

    constructor(props) {
        super(props);
        this.state = {
            isExpanded: false
        };
    }
}
Ponleu
  • 895
  • 7
  • 19
-23

delete the /* @flow */ in you code flite top

lee
  • 123
  • 5
  • More context should have been provided including possible options... i.e. rectify the flow setup or disable if not needed. – Joe Sep 09 '17 at 20:14