React on TypeScript に Action Creator は必要ない

公開日:2019-05-15
最終更新:2019-05-15

React Hooks on TypeScript に Action Creator は必要ない

まだReactもTypeScriptもはじめたばかりですが、そう感じました。
というわけで、まとめてみた。

そもそもAction Creatorって?

React HooksにはuseReducerという機能がある。これはReduxのreducerに近い機能であるそうだ。公式もそう言ってる。

(If you’re familiar with Redux, you already know how this works.)
引用元

ではこのuseReducerはどのように使うのか。簡単なサンプルを作ってみた。

// App.tsx  
import React, { useReducer } from 'react';  
import './App.css'  

const reducer = (oldCount: number, action: {type: string, state: number}) => {  
  switch(action.type){  
    case 'increment':  
      return oldCount + action.state;  
    case 'decrement':  
      return oldCount - action.state;  
    default:  
      throw new TypeError(`Illegal type of action: ${action.type}`);  
  }  
}  

const App: React.FC = () => {  
  const [count, dispatch] = useReducer(reducer, 0);  

  return (  
    <div className="App">  
      <h1>{count}</h1>  
      <button onClick={() => dispatch({type: 'increment', state: 1})}>INCREMENT</button>  
      <button onClick={() => dispatch({type: 'decrement', state: 1})}>DECREMENT</button>  
    </div>  
  );  
}  

export default App;  

ボタンを押せば数字が増えたり減ったりする、簡単なカウントアプリだ。
ここで、reducerの引数に注目してほしい。actionは以下の通りの型だと定義している。

action: {type: string, state: number}  

action.typeはincrementdecrementを受け取ったとき、正常に動作する。逆に言えば、異常な値であっても受け取ってしまうということだ。
正常な値を毎回確認するのは面倒だし、時間の無駄。ということで、Reduxでは公式リファレンスでAction Creatorsを紹介している
これを利用すると、前述のコードは以下の通りに修正できる。

import React, { useReducer } from 'react';  
import './App.css'  

const reducer = (oldCount: number, action: {type: string, state: number}) => {  
  switch(action.type){  
    case 'increment':  
      return oldCount + action.state;  
    case 'decrement':  
      return oldCount - action.state;  
    default:  
      throw new TypeError(`Illegal type of action: ${action.type}`);  
  }  
}  

const incrementCreator = (increment: number) => {  
  return {type: 'increment', state: increment}  
}  

const decrementCreator = (decrement: number) => {  
  return {type: 'decrement', state: decrement}  
}  

const App: React.FC = () => {  
  const [count, dispatch] = useReducer(reducer, 0);  

  return (  
    <div className="App">  
      <h1>{count}</h1>  
      <button onClick={() => dispatch(incrementCreator(1))}>INCREMENT</button>  
      <button onClick={() => dispatch(decrementCreator(1))}>DECREMENT</button>  
    </div>  
  );  
}  

export default App;  

前もってAction Creatorを定義しておき、必要に応じて呼び出すことで、誤ったActionを渡してしまうことがなくなるというわけだ。プログラマは安心してreducerを利用できるようになる。

ではなぜTypeScriptだとこのAction Creatorが不要になるかというと、型定義さえしっかりやっておけばTypeScriptが渡されたActionの安全性を保証してくれるからだ。

import React, { useReducer } from 'react';  
import './App.css'  

interface action {  
  type: 'increment' | 'decrement',  
  state: number  
}  

const reducer = (oldCount: number, action: action) => {  
  switch(action.type){  
    case 'increment':  
      return oldCount + action.state;  
    case 'decrement':  
      return oldCount - action.state;  
    default:  
      throw new TypeError(`Illegal type of action: ${action.type}`);  
  }  
}  

const App: React.FC = () => {  
  const [count, dispatch] = useReducer(reducer, 0);  

  return (  
    <div className="App">  
      <h1>{count}</h1>  
      <button onClick={() => dispatch({type: 'increment', state: 1})}>INCREMENT</button>  
      <button onClick={() => dispatch({type: 'decrement', state: 1})}>DECREMENT</button>  
    </div>  
  );  
}  

export default App;  

interfaceactionの型を定義した。この場合、typeにはincrementdecrementの文字列しか受け取れない。仮に違った文字列を入れた場合、それはactionとしてみなされず、TypeScriptはエラーを吐き出す。ちなみに他のエディタも同じかもしれないが、VSCodeは上記の通りに定義しておけばtypeを入力する際に自動補完してくれる。

もっと言うなら、interfaceを使わなくても以下の通りにすれば同じことができる。

const reducer = (  
  oldCount: number,  
  action: {type: 'increment' | 'decrement', state: number}  
  ) => { ...  

しかしこの場合、()の中身が多くなりすぎて見通しが悪くなる。個人的には前者の方法をお勧めしたい。

まとめ

TypeScriptって便利ですね。
Qiitaでは敗北者の話が人気でしたが、是非とも勝利者になれるように学んでいきたいですね。

記事が少しでもいいなと思ったらクラップを送ってみよう!
0
+1
だらだら更新していきたい技術ブログ

よく一緒に読まれている記事

0件のコメント

ブログ開設 or ログイン してコメントを送ってみよう
目次をみる

技術ブログをはじめよう

Qrunch(クランチ)は、ITエンジニアリングに携わる全ての人のための技術ブログプラットフォームです。

技術ブログを開設する

Qrunchでアウトプットをはじめよう

Qrunch(クランチ)は、ITエンジニアリングに携わる全ての人のための技術ブログプラットフォームです。

Markdownで書ける

ログ機能でアウトプットを加速

デザインのカスタマイズが可能

技術ブログ開設

ここから先はアカウント(ブログ)開設が必要です

英数字4文字以上
.qrunch.io
英数字6文字以上
ログインする