Using React(Native) + MobX + Flow, Flow treats @inject as error
Kay Gosho
Posted on April 10, 2018
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.
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,
// 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>
)
}
}
// 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:
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.
// 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
Posted on April 10, 2018
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.