「What the flux?」の翻訳
本投稿は以下の記事を日本語に翻訳したものになります。
(筆者の@jcreamer898氏に許可は頂いてます)
この記事は、Fluxについて物凄く分かりやすく書かれているので、「Flux
難しい!」って言う方の助けになれば幸いです(*^^)v
以下、本文です。 ↓↓↓
What the flux?
私はこの数週間、私の脳をReact.jsとFluxアーキテクチャーでぐるっと包み込むことに没頭してきました。
嘘をつくつもりはありませんが、私はそれを避けていました。FluxやReactについてのドキュメントやブログ記事を見ると、私の脳は…
componentDidMount
やDispatchers
、ActionCreators
など色んなものが、私が中に踏み入ろうと試みたときに、私を怖がらせました。それはちょうどコンピュータのようなものでした。数日経ちましたが、今では私はこれが好きです。本当に。
Fluxで私の頭をしっかりと包み込むのに数日かかりました。特にこの画像。
私はついにそれを取り巻くもので私の頭を包み込むようになりましたが、他の人がもう少し早くFluxを理解するのを手助けするために、私自身のバージョンを考え出すことにしました。
ではこの全てを解体してみましょう…
Views
Show some stuff.
ビューはコンポーネントがレンダリングされるものです。あなたのコンポーネントにはいくつかの役割をがありますが、例えば次のようなものがあります。
var NewEmailComponent = React.createClass({ getInitialState() { return { to: "" }; }, render() { return ( <input name="to" type="email" onChange={this.updateToText} /> <button onClick={this.createNewEmail}>New Email</button> ); }, updateToText(event) { this.setState({ to: event.target.value }); }, createNewEmail(event) { var to = this.state.to; EmailActionCreator.createNewEmail(to); } });
上記から分かるように、Reactのすべてのコンポーネントには状態があります。私たちのNewEmailComponent
は、まず初めに to:""
という状態を持ちます。
次に、render
は表示するJSXを返します。ここでは入力とボタンがあります。
onChange = {this.updateToText}
とonClick = {this.createNewEmail}
に気づいたでしょう。これらの両方が、イベントハンドラをコンポーネントに追加し、それぞれの関数を呼び出しています。
to
の入力テキストが変更されると、to
の変更内容で状態が変更されます。
Action Creators
Go get some more stuff
アクション作成者は"アクション"を作成します。はい。それと、必要に応じてサーバーからデータを取得するのが一般的です。 だから、少しの間ビューに戻ってみましょう…
ボタンをクリックすると、EmailActionCreator.createNewEmail(to)
関数がto
に渡すデータの種類に関係なく発火します。
ID、名前、何でもかまいません。今回の例ですと、送信する電子メールになります。
EmailActionCreator.createNewEmail
関数はいくつかのことを行います。
- 新しい電子メールを作成するアクションを作成
- APIをコールして下書きを作成
Actions
Do something with stuff
アクションはJavaScript POJOs(plain old javascript objects)のことです。
大抵、慣例によってtype
といくつかのdata
を持っています。
どのように、そしてなぜそれらが作られたのか、まず初めに一歩引いて考えてみましょう。
さて、私たちのアクション作成者は “action"を作成します。 一般的には、可能な限りの異なるアクションタイプのオブジェクトを、すべて格納するファイルがあります。
// actions/fooActions.js var keyMirror = require('keymirror'); module.exports = keyMirror({ CREATE_EMAIL: null, EMAIL_CREATED: null, SEND_EMAIL: null });
あなたはこれらのアクションを使用して、UIまたはサーバーからトリガーできるものを定義します。
今回の例でkeyMirrorはnull
の値を作成するために使用され、大文字のキー名はミラーリングされます。
いわゆる、ショートカットのライブラリです。
では、EmailActionCreator
に戻って、これらの異なるアクションタイプを使ってみましょう。
// actions/emailActionCreator.js module.exports = { createNewEmail(to) { EmailAppDispatcher.handleViewAction({ type: ActionTypes.CREATE_EMAIL, to: to }); EmailWebService.createEmail({ to: to }); }, emailCreated(mail) { EmailAppDispatcher.handleServerAction({ type: ActionTypes.EMAIL_CREATED, mail: mail }); } }
EmailWebService
はあなたのAPIをたたくことができますが、あなたが望むのなら…
// data/emailWebService.js module.exports = { createEmail: function(options) { $.ajax({ url: "/api/email", type: "POST" }).done(function(id) { var mail = { to: options.to, id: id }; EmailActionCreator.emailCreated(mail); }); }; };
ここでは、jQuery.ajax
を使用して新しい電子メールを作成しています。
電子メールの作成が完了すると、電子メールが作成された全員に伝えるために、もう一つ別のアクションがEmailActionCreator.emailCreated(mail);
と共に作成されます。このアクションのタイプはActionTypes.EMAIL_CREATED
です。
次にディスパッチャーと、そのhandleViewAction
およびhandleServerAction
要素について話します。
Dispatcher
Hey Everyone! There’s new stuff!
ディスパッチャの唯一の仕事は、何らかのメッセージ、またはイベント、あるいはあなたが呼び出したいものを公開して、 変更を検知しようとしている人に何かが起こったことを知らせることです。
例えば、誰かが最初にCreate Email
ボタンをクリックしたときに、EmailActionCreator
によって1つのアクションが作成され、
ディスパッチャ上のhandleViewAction
メソッドを介してディスパッチャに送信されます。
ディスパッチャは一度生成されるとまったく変更する必要のない定型コードです…
var EmailAppDispatcher = assign(new Dispatcher(), { handleServerAction(action) { var payload = { source: PayloadSources.SERVER_ACTION, action: action }; this.dispatch(payload); }, handleViewAction(action) { var payload = { source: PayloadSources.VIEW_ACTION, action: action }; this.dispatch(payload); } }); module.exports = EmailAppDispatcher;
Flux.jsには他のいくつかの間(*1)で、register
とdispatch
機能を持つデフォルトのディスパッチャが備わっています。
私たちのEmailAppDispatcher
には、handleViewAction
とhandleServerAction
という2つのヘルパー関数があります。
この2つの異なる関数は絶対に必要なものではありませんが、もし必要になった場合、アクションがどこから来たのかを正確に知ることができます。
とは言うものの、Fluxのdefault Dispatcherから組み込みのdispatch
関数を呼び出すだけです。
アプリ内の他の場所では、次に話しますが任意のストアも、ディスパッチャのregister
関数を使うと、アクションが送信されていることが通知されます。
Store
Keep track of stuff
ストアはアプリケーションの状態とビジネスロジックを保持します。 また彼ら自身も一般的にはイベントエミッタです。 これは、あなたはストアが公開したイベントを受け取ることができる、と言うことを意味します。 したがって、ビューはストアの変更イベントにバインドされ、異なるストアメソッドを呼び出してデータを取得し、新しいデータで状態を更新します。
理想的には、ストアがajaxリクエストを行わないことです。なぜなら、アクションはデータを送信する必要があり、ストアはそれを管理するだけなので。
ストアは通常、ある種のデータ / 状態を保持するローカル変数を持ちます。つまり、以下の場合では、単なるアクティブな電子メールになります。
var EventEmitter = require("events"), assign = require("react/lib/assign"), Email = require("./core/email"), _ = require("underscore"); var CHANGE_EVENT = "change"; var activeEmail = null; function createNewEmail(mail) { var email = new Email(mail); activeEmail = email; } var EmailStore = assign({}, EventEmitter.prototype, { emitChange() { this.emit(CHANGE_EVENT); }, addChangeListener(callback) { this.on(CHANGE_EVENT, callback); }, removeChangeListener(callback) { this.removeListener(CHANGE_EVENT, callback); }, getActiveEmail() { return activeEmail; } });
emitChange
、addChangeListener
、およびremoveChangeListener
は各ストアで目にする関数であり、かつ基になるEventEmitter
のメソッドemit
、on
そしてremoveListener
の抽象クラスです。
CHANGE_EVENT
は変更イベントの名前の文字列を保存するだけです。
getActiveEmail
メソッドはアクティブな電子メールを返します。
ディスパッチャに再度バックアップし、register
関数を公開することを覚えておいてください。
上記のようにストアのためのメソッドを定義した後、私たちはディスパッチャに「登録」します…
EmailStore.dispatchToken = EmailAppDispatcher.register((payload) => { var action = payload.action; switch (action.type) { case ActionTypes.EMAIL_CREATED: createNewEmail(action.mail); EmailStore.emitChange(); break; } });
ディスパッチャが任意のアクションを送信するたびに、register
関数がコールされます。
ただし、switch文に型が含まれている場合にのみ注意します。今回のケースではActionTypes.EMAIL_CREATED
だけです。
ディスパッチャから送信されたアクションがActionTypes.EMAIL_CREATED
である場合、単にアクティブな電子メールを設定するだけのcreateNewEmail
関数をコールしてレスポンスを返します。
この時、変更イベントを発行するようにストアに指示します。
一連の流れに戻り、もう一度やり直してみましょう…
var EmailStore = require("../stores/emailStore"); /** ... *./ { componentWillMount() { EmailStore.addChangeListener(this._onChange); }, _onChange() { this.setState({ activeEmail: EmailStore.getActiveEmail() }); } }
componentWillMount
関数はコンポーネントの準備が整うと発火します。
componentWillMount
はストアに変更リスナーを追加することができる変更イベントです。
ストアが変更されるたびに、this._onChange
がコールされます。
_onChange
関数にて作成された新しい電子メールでコンポーネントの状態を設定できます!
ドン。
TL;DR(要約)
View Renders ->
Click triggers action creator ->
Go get data ->
Create action for recieved data ->
Send action to dispatcher ->
Dispacther publishes action ->
Store listens for action ->
Store updates state ->
View updates
さて、今あなたの心はどちらかでしょう…
もしくは…
もしあなたがテーブルをひっくり返したい場合は、この記事をもう一度読んで、これらの例を見て、やり直してみてください。 あなたはそれ(Flux)を手に入れ、そしてあなたは愛するでしょう。
終わりに
翻訳記事を投稿する許可を下さいました@jcreamer898氏、ありがとうございました!! 改めて御礼申し上げます。
さて、誰かの英語記事を丸々翻訳して投稿するのは今回が初めてでしたが、物凄い勉強になりました。 また、自分の日本語が下手すぎることも痛感しました。色んな本読んで、表現力を身に着けたいものです。
冒頭にも書きましたが、この記事がこれからFlux
を学ぼうとしている方の理解を助けることができれば幸いです。では。
*1:ここだけ意味がわかりませんでした。原文は「amoung a few others」