Using React(Native) + MobX + Flow, Flow treats @inject as error
Tags: react, reactnative, flow, javascript
Published: 2018-04-10 17:25:21

---
title: Using React(Native) + MobX + Flow, Flow treats @inject as error
published: true
description: 
tags: React, ReactNative, Flow, JavaScript
---

This is a story for flow, who doesn't understand ESNext Decorator.

# Overview

Flow, who checks static type of  JS(X), does not understand Decorator of ES Proposal (Stage 1, 2018/04/11).

At first, Flow does not pass if we use Decorators (like `@inject`).
We should add the following configuration to `.flowconfig` to execute flow check with Decorators.

```ini
esproposal.decorators=ignore
```

However, this let flow ignore Decorators so he does not interpret them.
Thus, he claims errors if we use `@inject` to inject MobX's store in React components.

To handle this error, the only one choice is not to use Decorators.

Another possible choice is to `defaultProps` as this article, suggests,

https://wietse.loves.engineering/using-flowtype-with-decorators-in-react-af4fe69e66d6

but I think we should avoid that kind of HACK because it increases undesirable types, and we cannot trust `Props` anymore.

# Prerequisite

- Developing with React(Native) + MobX + Flow
- Installed `babel-plugin-transform-decorators-legacy`
- Not select the easiest way using `Component<*>` or `$flowFixMe`

# Problem

When `@inject` cause errors,

```jsx
// App.jsx

// @flow

import { React, Component } from 'react'
import SomeComponent from './SomeComponent'
import Stores from './stores'

const stores = new Stores()

class App extends Component<{}> {
  render() {
    return (
      <Provider stores={stores}>
        <ScrollView>
          <SomeComponent someProperty="Hello" />
        </ScrollView>
      </Provider>
    )
  }
}
```

```jsx
// SomeComponent.jsx

// @flow

import { React, Component } from 'react'
import SomeStore from './stores/SomeStore'

type Props = {
  someStore: SomeStore<*>;
  someProperty: string;
}

@inject('someStore')
@observer
export default class SomeComponent extends Component<Props> {
  render() {
    const { someProperty, someValue } = this.props.someStore

    return ( 
      <Text>{someProperty}, {someValue}</Text>
    )
  }
}
```

When we run `flow check` in our console, Flow creates the following error:

```sh
Property `someStore` is incompatible:

# ...

property `someStore`. Property not found in. see `SomeComponents.js`

# ...

props of React element `SomeComponent`
```

Let me describe how Flow feels.
He ignores Decorators so he doesn't understand Decorators.
Flow is nice guy, so he are focusing what he should do.

But we would like to use Decorators regardless to his policy.

# Solution

Really simple, as if I don't have to write this article.

We should give up to use `@inject` until Flow supports it. Instead, we use `inject` as a normal JavaScript function.
I think this does not influent code readability.

```jsx
// SomeComponent.js (part)

@observer
class SomeComponent extends Component<Props> {
  render() {
    const { someProperty, someValue } = this.props.someStore

    return ( 
      <Text>{someProperty}, {someValue}</Text>
    )
  }
}

export default inject('someStore')(SomeComponent)
```

Very simple solution, but for ES beginner it took much time to hit this solution.

Hope this article helps you.

# Refs

https://gist.github.com/vonovak/29c972c6aa9efbb7d63a6853d021fba9