前回React.jsの理解を深めるために楽天トラベル空室検索APIを使ったホテル検索アプリケーションを自作しました。
axiosを使って非同期通信をしたり、初めてMaterial-UIを導入してみたり、理解を深める最初の一歩には良かった題材だったと思います。
そして第二弾としてTwitter APIを利用したTwitterクライアントを作成中です!前回できなかったことを盛り込んだ練習をしようと思い、その一つにFlow Typeを入れました。(Twitterクライアントに関するスキルセット等はまた後日。)
参考にしたサイトの中で、
- FLOW Redux(公式サイト)
- Flow: Type Checking with Flow in React + Redux
- react-reduxにflowtypeを導入しPropsに型を付ける
が大変役立ちました!
チュートリアルはこちらですね。
Youtubeもありますので、導入にはオススメです!
【Flowを導入する手順】
①ライブラリインストール
Flowtypeに必要なライブラリをインストールします。
(私は以下をインストールしましたが、お好みでインストールを。
$ yarn add -D @babel/preset-flow eslint-plugin-flowtype flow-bin
②webpack.config.jsに追記
webpack.config.jsに@babel/preset-flow
を追加しました。
module.exports = {
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: [
{
loader: 'babel-loader',
options: {
presets: [
'@babel/preset-env',
'@babel/preset-react',
'@babel/preset-flow', //追加
],
},
},
{
loader: 'eslint-loader',
},
],
以下省略
}
③.flowconfigファイルを作成
.flowconfigファイルを新規作成して、以下のような記述をしました。
[ignore]
.*/node_modules/.*
.*/dist/.*
[include]
[libs]
flow-typed
[lints]
[options]
module.name_mapper='^@app\(.*\)$' -> '<PROJECT_ROOT>/src/js/\1'
[strict]
④ソースコードに// @flow
を頭につけて、型宣言開始!
ソースコードの一番上に// @flow
を書いて、初めていきましょう!
これから実際に変更したソースコードをご紹介していきます。
複雑なことはあまりしていません。
【変更したソースコード】
コンポーネント
prop-types
を使っていましたが、propTypesで記述していた箇所は全削除しましょう!
以下の記述の通り、mapStateToProps
で渡ってくるデータをStateProps
、mapDispatchToProps
で渡す関数をDispatchProps
で型宣言しています。
authは外部APIを使用してるのでany
にしました。
その下にコンポーネント内で使うthis.state
をState
で型宣言しています。
type StateProps = {
auth: any,
}
type DispatchProps = {
authTwitter: () => Promise<Object>,
twitterSignOut: () => Promise<Object>,
getUserAccount: () => Promise<Object>,
}
type Props = StateProps & DispatchProps
type State = {
dialogOpen: boolean,
}
class TwitterAuth extends React.Component<Props, State> {
state = {
dialogOpen: false,
}
static defaultProps = {
authTwitter: () => {},
twitterSignOut: () => {},
getUserAccount: () => {},
}
以下省略
}
const mapStateToProps: Object = (state: StateProps) => ({
auth: state.auth,
})
export default withRouter(
connect(
mapStateToProps,
{ authTwitter, twitterSignOut, getUserAccount }
)(TwitterAuth)
)
また、イベント系は引数をevent: SyntheticEvent<*>
に変えました。
handleChange = (event: SyntheticInputEvent<HTMLInputElement>) => {
省略
}
handlePostTweet = (event: SyntheticEvent<*>) => {
省略
}
Reducer
Reducerは複雑なことはしていません。
引数のstateとactionの型を宣言したのと、帰ってくる値を: Object
で追加してあげました。
export default (state: Object = INITIAL_STATE, action: Object): Object => {
switch (action.type) {
case GET_TIMELINE_REQUEST:
return {
省略
Action
Actionの記述は以下のようにしています。
見るとお分かりかと思いますが、Flow公式サイトの通りに実装しています。
Typing Redux reducers
https://flow.org/en/docs/react/redux/#toc-typing-redux-reducers
type State = Object
type Action =
| { type: AUTH_TWITTER_REQUEST }
| { type: AUTH_TWITTER_SUCCESS, payload: State }
| { type: AUTH_TWITTER_ERROR, error: Object }
| { type: USER_SIGN_IN, payload: Object }
| { type: USER_SIGN_OUT }
type Dispatch = (action: Action | ThunkAction | PromiseAction) => any
type GetState = () => State
type ThunkAction = (dispatch: Dispatch, getState: GetState) => any
type PromiseAction = Promise<Action>
export const authTwitter = (): ThunkAction => async dispatch => {
...
}
今のところファイル分割しているActionコンポーネント全てに上記の記述をしてますので、もしかしたらまとめられるのかもです。
【触れてみた感想】
運用中のアプリケーションやブログ、公式サイト見てきましたが、書き方は人によってそれぞれだと思いました!
使用しているライブラリのバージョンが新しすぎるとFlowtypeが対応してなかったりします。(実は記事ではあげてませんが、まだエラーが残っていたりします。。)
回避方法をググりまくっていますので、エラー出てしまっている箇所は解決次第追記していきます。
【最後に】
まだ私が触ったのはFlowtypeの基本のキだと思います。
実際に運用されている案件の型宣言を見ると、まだ「なんだこれは…!」と思ってしまいます^_^;
個人的にTypescriptを習得したい…!その前にテストについて調べねば。そしてそしてReact.js関連(Next.jsとかGatsbyとか)も習得したいです。
下の記事が参考になりましたので、さらに理解を深めてまいります。