Redux で API を使って外部と通信をするのに適切なレイヤーは Action Creator が良いとされています。
😼 Action Creator について
Action Creator とは、Action を作るためのロジックを記載する部分です。
function setUserName(userName) { return { type: "SET_USER_NAME", UserName }; }
|
Action Creator はシンプルな Action オブジェクトを返す想定になっており、同期処理が前提となります。
🐡 Action Creator での非同期処理
Action Creator で非同期処理を行うためには、以下の middleware を使うのが一般的なようです。
🐝 Sample Code for Redux Thunk
Reddit API を Redux Thunk を使って呼び出すサンプルコードが、Redux の公式ドキュメントに公開されています。
大変わかりやすいサンプル実装ですので、ぜひ読んでサンプルコードを実装してみてください。
Example: Reddit API - Redux
🍄 Middleware を使わない実装
redux-thunk
や redux-saga
は学習コストが高いため、それらを使わずに実装するというアイデアもあります。
https://qiita.com/uryyyyyyy/items/d8bae6a7fca1c4732696
A component
サンプルとなるコンポーネントです。
import React, { Component } from "react"; import { ActionClass } from "./Actions";
type Props = { someState: SomeState, actions: ActionClass };
export class Counter extends Component<void, Props, void> { render() { const loading = this.props.value.loadingCount === 0 ? null : <p>loadingp>; return ( {loading} {`score: ${this.props.value.num}`}</p> Increment 3 button> async Increment 100 </button> div> ); } }
|
ActionClass
ActionCreator
をまとめたクラスです。
export const INCREMENT = "counter/increment"; export const FETCH_REQUEST_START = "counter/fetch_request_start"; export const FETCH_REQUEST_FINISH = "counter/fetch_request_finish";
export class ActionClass { dispatch: (action: any) => any;
constructor(dispatch: (action: any) => any) { this.dispatch = dispatch; }
increment(amount: number) { this.dispatch({ type: INCREMENT, amount: amount }); }
async asyncIncrement(): Promise<void> { this.dispatch({ type: FETCH_REQUEST_START });
try { const response: Response = await fetch("/api/count", { method: "GET", headers: headers, credentials: "include" });
if (response.status === 200) { const json: JsonObject = await response.json(); this.dispatch({ type: INCREMENT, amount: json.amount }); } else { throw new Error(`Illegal status code: ${response.status}`); } } catch (err) { console.error(err.message); } finally { this.dispatch({ type: FETCH_REQUEST_FINISH }); } } }
|
Container
ActionClass と Component をつなぎこむ Container の実装サンプルです。
import * as React from "react"; import { connect } from "react-redux"; import type { Dispatch } from "redux"; import { Counter } from "./Counter"; import { ActionClass } from "./Actions";
const mapStateToProps = (state: any) => { return { someState: state.someState }; };
const mapDispatchToProps = (dispatch: Dispatch) => { return { actions: new ActionClass(dispatch) }; };
export default connect( mapStateToProps, mapDispatchToProps )(Counter);
|
🐰 Appendix
Redux の 2 つの Component について
Redux には「Container Component」と「Presentational Component」の 2 種類の Component が存在します。
Container Component
Redux の store のデータを Presentational Component に紐付けるための Component。
import { connect } from "react-redux"; import PostList from "~/components/post/PostList";
const mapStateToProps = state => { const length = state.posts.length; const currentState = state.posts[length - 1]; return { posts: currentState.items }; };
const GetPostList = connect(mapStateToProps)(PostList);
export default GetPostList;
|
Presentational Component
React の一般的な Component。Container Component で紐付けられたデータを実際に利用して描写する Component。
import React from "react"; import PropTypes from "prop-types"; import Post from "./Post";
const PostList = ({ posts }) => ( {posts.map((post, index) => ( ))} </ul> );
export default PostList;
|
🐮 References
🖥 VULTRおすすめ
「VULTR」はVPSサーバのサービスです。日本にリージョンがあり、最安は512MBで2.5ドル/月($0.004/時間)で借りることができます。4GBメモリでも月20ドルです。
最近はVULTRのヘビーユーザーになので、「ここ」から会員登録してもらえるとサービス開発が捗ります!