react-reduxにflowtypeを導入しPropsに型を付ける
flowtypeを導入したとき、reactとreduxをつなぐ部分の情報が少なかったのでまとめます。
flowtypeの導入前
比較として導入前のソースを載せておきます。
import React, {PropTypes, Component} from 'react' import {connect} from 'react-redux' import * as actions from '../actions class SamplePage extends Component { render() { const {title, description, myAction} = this.props return ( <div> <button onClick={myAction}>{title}</button> <p>{description}</p> </div> ) } } SamplePage.propTypes = { title: PropTypes.string, description: PropTypes.string, myAction: PropTypes.func } const mapStateToProps = state => { return { title: state.title, description: state.description } } const mapDispatchToProps = dispatch => { return { myAction: () => dispatch(actions.myAction()) } } export default connect(mapStateToProps, mapDispatchToProps)(SamplePage)
導入後
これが導入後のソースです。propTypesが消えましたが、typeを記述しているので行数はあまり変わっていません。
import React, {Component} from 'react' import {connect} from 'react-redux' import * as actions from '../actions import type {MapStateToProps, MapDispatchToProps} from 'react-redux' type StateToProps = { title: string, description: string } type DispatchToProps = { myAction: () => void } type Props = StateToProps & DispatchToProps class SamplePage extends Component<void, Props, void> { render() { const {title, description, myAction} = this.props return ( <div> <button onClick={myAction}>{title}</button> <p>{description}</p> </div> ) } } const mapStateToProps: MapStateToProps<*, *, StateToProps> = state => { return { title: state.title, description: state.description } } const mapDispatchToProps: MapDispatchToProps<*, *, DispatchToProps> = dispatch => { return { myAction: () => dispatch(actions.myAction()) } } export default connect(mapStateToProps, mapDispatchToProps)(SamplePage)
ポイント
propTypes
が3つのtype
に置き換えられています。
その中で特に大事なところが以下で、
type Props = StateToProps & DispatchToProps
mapStateToProps
とmapDispatchToProps
で生成された2つのオブジェクトのtypeが合成されたものが、
class SamplePage extends Component<void, Props, void> { ...
となりcomponentに渡されていることを明示的に示すことができます。
補足1
MapStateToProps
は以下のように定義されています。
declare type MapStateToProps<S, OP: Object, SP: Object> = (state: S, ownProps: OP) => SP;
ジェネリクスで、SとOPを受け取ってSPを返す関数という型になってますね。
導入後のソースではMapStateToProps<*, *, StateToProps>
のように宣言しています。
Stateのtypeを宣言していれば、MapStateToProps<State, *, StateToProps>
となり、MapStateToProps
内のstateに対して型が適用されるのでSやOPに対しても型の宣言をすることをオススメします。
補足2
2018/02/01現在で最新のflowtypeではComponentに渡すPropsの型を以下のように記述します。
class SamplePage extends Component<Props> { ...