GreenAsJade
GreenAsJade

Reputation: 14685

How to help flow handle react component state initialiser?

I have this kind of initialisation going on in my React components:

export default class LoginForm extends Component {
    state = {      // (*)
        flash: {
            message: null,
            style: null
        } // initialiser for flash message: show nothing
    }
    showError(error_message: string) {
        this.setState({
                flash: {
                    message: error_message,
                    style: "danger"
                })
        }

Unfortunately, flow is treating the initialisation of the flash property of the state object as a type declaration, and in the subsequent setState() it flags the new declaration of the value of the flash property as a type mismatch ("string is incompatible with null").

How can I tell flow what is actually going on here, and thus avoid it reporting an error?


(*) note: I originally erroneously had a : in this line instead of = ... @DanPrince corrected that.

Upvotes: 0

Views: 636

Answers (2)

Peter Hall
Peter Hall

Reputation: 58735

The type for React.Component can be parameterized with the prop types and state type.

type LoginProps = {
    // props here
}
type LoginState = {
    flash: {
        message: ?string,
        style: ?string
    }
}

export default class LoginForm extends Component<LoginProps, LoginProps, LoginState> {
    state : LoginState = { flash: { message: null, style: null } }
    showError(error_message: string) {
        this.setState({
                flash: {
                    message: error_message,
                    style: "danger"
                }
        })
    }
}

This should help Flow reconcile all the types correctly.

Upvotes: 0

Dan Prince
Dan Prince

Reputation: 29989

Did you mean to use the class properties syntax instead?

export default class LoginForm extends Component {
  state = {
    flash: { message: null, style: null }
  }
}

As far as I'm aware, specifying class properties with : isn't and hasn't ever been a valid syntax. In this case, I would say that it's the expected behaviour for Flow to treat it as a type declaration.

If you want to create a class property and give it a type signature, you'd need to combine the two syntaxes.

class LoginForm extends Component {
  state
    : { flash: { message: ?string, style: ?Object } }
    = { flash: { message: null, style: null } };
}

Or in the generic case:

class {
  property:Type = Value;
}

Upvotes: 2

Related Questions