Flux Utilsのドキュメント日本語訳

JavaScriptの世界を反映するかのようにFluxのフレームワークも案の定玉石混合の状態となっています。Reduxが一つ頭抜け出したかなと言った状況ですが、Reduxはすでにロックインしてるので、Facebookのflux/utilsを使うのがいいよという話もあったりします。自分もいまだにどのフレームワークを使ったらいいのか決めあぐねているので、flux/utilsの勉強のためにFlux Utilsのドキュメントを日本語に訳してみることにしました。

はじめに

flux-logo

まずはじめにこの記事は以下のFlux Utilsのドキュメントを日本語に翻訳したものとなります。日本語と一緒に原文も載せてありますが、フォントを小さくしていて読みにくいです。なので英文で読みたい方は本家にてどうぞ。

それからこのFlux Utilsを理解するには、ある程度fluxについて仕様なり、仕組みなり理解している必要があります。それに最適なのがFluxのDispatcherのドキュメントだと思っています。当ブログでも以前にこのDispatcherのドキュメントの和訳やFluxの実装のポイントをまとめた記事を投稿しています。こちらも併せて目を通していただけたらと思います。

それでは、以下よりFlux Utilsのドキュメントの日本語訳となります。

Flux Utils(日本語訳)

Flux Utils is a set of basic utility classes to help get you started with Flux. These base classes are a solid foundation for a simple Flux application, but they are not a feature-complete framework that will handle all use cases. There are many other great Flux frameworks out there if these utilities do not fulfill your needs.

Flux Utilsは、Fluxを始めるのを助けてくれるベースユティリティclassのセットです。これらベースclassはシンプルなFluxアプリケーションのための強固な基盤となりますが、すべての用途に対応するような画期的で完成されたフレームワークではありません。これらのユーティリティがあなたのニーズを満たさない場合は、世の中には他に多くの素晴らしいFluxフレームワークがありますので(そちらをお使いください)。

Usage

There are four main classes exposed in Flux Utils:

Flux Utilsには、4つの主要なclassがあります。

  1. Store
  2. ReduceStore
  3. MapStore
  4. Container

These base classes can be imported from flux/utils like this:

これらのベースclassは以下のようにflux/utilsからimportして使います。

import {ReduceStore} from 'flux/utils';

class CounterStore extends ReduceStore {
  getInitialState(): number {
    return 0;
  }

  reduce(state: number, action: Object): number {
    switch (action.type) {
      case 'increment':
        return state + 1;

      case 'square':
        return state * state;

      default:
        return state;
    }
  }
}

Best practices

There are some best practices we try to follow when using these classes:

これらのclassを使う時に従っておきたいいくつかのベストプラクティスを紹介します。

Stores

  1. 1. Cache data
  2. 2. Expose public getters to access data (never have public setters)
  3. 3. Respond to specific actions from the dispatcher
  4. 4. Always emit a change when their data changes
  5. 5. Only emit changes during a dispatch
  1. データをキャッシュしましょう。
  2. データにアクセスするためのパブリックなgetterを公開しましょう(publicなsetterは決して持ってはいけません)。
  3. dispatcherからの特定のactionに応答しましょう。
  4. データに変更があった際は常に変更をemit(発火)しましょう。
  5. dispatchしている時は変更をemitするだけにしましょう。

Actions

  1. 1. Describe a user’s action, are not setters. (e.g. select-page not set-page-id)
  1. setterではなく、ユーザーのアクションを記述しましょう。(例. set-page-idではなくselect-page

Containers

  1. Are react components that control a view
  2. Primary job is to gather information from stores and save it in their state
  3. Have no props and no UI logic
  1. viewをコントロールするReactコンポーネントになるようにしましょう。
  2. 主な役割はstoreからの情報を寄せ集め、それをstateに保存することです。
  3. propsとUIロジックは持たないようにしましょう。

Views

  1. 1. Are react components that are controlled by a container
  2. 2. Have all of the UI and rendering logic
  3. 3. Receive all information and callbacks as props
  1. containerによってコントロールされるReactコンポーネトになるようにしましょう。
  2. UIとレンダリングのロジックのすべてを持ちましょう。
  3. propsを通してすべての情報とコールバックを受け取りましょう。

API

Store

constructor(dispatcher: Dispatcher) Constructs and registers an instance of this store with the given dispatcher.

constructor(dispatcher: Dispatcher) dispatcherを受け取り、storeのインスタンスの作成と登録を行います。

addListener(callback: Function): {remove: Function} Adds a listener to the store, when the store changes the given callback will be called. A token is returned that can be used to remove the listener. Calling the remove() function on the returned token will remove the listener.

addListener(callback: Function): {remove: Function} storeにlistenerを追加します。storeに変更があった際に、受け取ったコールバックが実行されます。listenerを削除するために使われるtokenが返されます。remove()関数を実行すると、返されたtokenを元にlistenerが削除されます。

getDispatcher(): Dispatcher Returns the dispatcher this store is registered with.

getDispatcher(): Dispatcher Storeに登録されたdispatcherを返します。

getDispatchToken(): DispatchToken Returns the dispatch token that the dispatcher recognizes this store by. Can be used to waitFor() this store.

getDispatchToken(): DispatchToken dispatcherがstoreを認識するために使われるdispatch tokenを返します。storeをwaitFor()するために使われます。

hasChanged(): boolean Ask if a store has changed during the current dispatch. Can only be invoked while dispatching. This can be used for constructing derived stores that depend on data from other stores.

hasChanged(): boolean storeが現在のdispatch時に変更されたかどうか尋ねます。dispatchしている間にのみ呼び出すことができます。他のstoreからのデータに依存しているstoreを作成するために使われます。

__emitChange(): void Emit an event notifying all listeners that this store has changed. This can only be invoked when dispatching. Changes are de-duplicated and resolved at the end of this store’s __onDispatch function.

__emitChange(): void すべてのlistenerにstoreに変更があったことを通知するためのeventをemitします。dispatchしている間にのみ呼び出すことができます。変更は、storeの__onDispatch関数の終了時点でde-duplicate(複製されたものが削除)され、解決されます。

__onDispatch(payload: Object): void Subclasses must override this method. This is how the store receives actions from the dispatcher. All state mutation logic must be done during this method.

__onDispatch(payload: Object): void サブクラスはこのメソッドをoverrideしなくてはいけません。というのは、storeはdispatcherからactionを受け取るからです。すべてのstateのmutation(変更)のロジックはこのメソッドの実行時になされなくてはいけません。

ReduceStore<T>

extends Store This class extends the base Store.

extends Store このclassはStore(ベース)を継承します。

getState(): T Getter that exposes the entire state of this store. If your state is not immutable you should override this and not expose state directly.

getState(): T storeの全体のstateを公開するgetterです。あなたのstateがまだimmutableでないのなら、これをoverrideし、直接stateを公開しないようにすべきです。

getInitialState(): T Constructs the initial state for this store. This is called once during construction of the store.

getInitialState(): T storeのために初期stateを作成します。storeの作成時に一度だけ呼び出されます。

reduce(state: T, action: Object): T Reduces the current state, and an action to the new state of this store. All subclasses must implement this method. This method should be pure and have no side-effects.

reduce(state: T, action: Object): T 現在のstateと、storeの新しいstateのためのactionをreduceします。すべてのサブクラスはこのメソッドを実装しなくてはいけません。このメソッドはpureであり、side-effectを持つべきではありません。

areEqual(one: T, two: T): boolean Checks if two versions of state are the same. You do not need to override this if your state is immutable.

areEqual(one: T, two: T): boolean stateの2つのバージョンが同じかどうかチェックします。stateがimmutableであれば、これをoverrideする必要はありません。

Doesn’t need to emit a change Note that any store that extends ReduceStore does not need to manually emit changes in reduce() (you still can if you want to though). The state is compared before and after each dispatch and changes are emitted automatically. If you need to control this behavior (perhaps because your state is mutable) override areEqual().

Doesn’t need to emit a change ReduceStoreを継承するどんなstoreもreduce()において手動で「変更」をemitする必要はないということにご注意ください(それでもしたかったら、しても大丈夫です)。stateはそれぞれのdispatchの前後で比較され、「変更」は自動でemitされます。(おそらくあなたのstateがmutableのせいで)この振る舞いをコントロールしたければ、areEqual()をoverrideしてください。

MapStore<K, V>

extends ReduceStore<Immutable.Map<K, V>> This class extends ReduceStore and defines the state as an immutable map.

extends ReduceStore<Immutable.Map<K, V>> このclassはReduceStoreを継承し、immutableなmapとしてstateを定義します。

at(key: K): V Access the value at the given key. throws an error if the key does not exist in the cache.

at(key: K): V 与えられたkeyの値にアクセスします。keyがcacheになかった場合はerrorを投げます。

has(key: K): boolean Check if the cache has a particular key

has(key: K): boolean cacheが特定のkeyを持っているかチェックします。

get(key: K): ?V Get the value of a particular key. Returns undefined if the key does not exist in the cache.

get(key: K): ?V 特定のkeyの値をGetします。もしcacheの中にkeyが存在しない場合はundefinedを返します。

getAll(keys: Iterable<K>, prev: ?Immutable.Map<K, V>): Immutable.Map<K, V> Gets an array of keys and puts the values in a map if they exist, it allows providing a previous result to update instead of generating a new map. Providing a previous result allows the possibility of keeping the same reference if the keys did not change.

getAll(keys: Iterable<K>, prev: ?Immutable.Map<K, V>): Immutable.Map<K, V> keyが存在していたら、keyの配列をgetし、値をmapにセットします。それは新しいmapを生成する代わりに、引数で与えられた前の結果を更新することを可能にします。keyに変更がなかった場合、前の結果を引数で与えることによって、同じ参照を保持することを可能とします。

Container

create(base: ReactClass, options: ?Object): ReactClass Create is used to transform a react class into a container that updates its state when relevant stores change. The provided base class must have static methods getStores() and calculateState().

create(base: ReactClass, options: ?Object): ReactClass CreateはReactのclassをcontainerに変換するために使われます。containerは関連のあるstoreに変更があった時に、そのstateをupdateします。引数にセットされるベースclass(ReactのClass)はgetStores()calculateState()の静的なメソッドを持たなければいけません。

import {Component} from 'react';
import {Container} from 'flux/utils';

class CounterContainer extends Component {
  static getStores() {
    return [CounterStore];
  }

  static calculateState(prevState) {
    return {
      counter: CounterStore.getState(),
    };
  }

  render() {
    return ;
  }
}

const container = Container.create(CounterContainer);

Additional options may be provided when creating your container in order to control certain behaviors.

追加でオプションを与えることで、確実な振る舞いをコントロールするようにcontainerを作ることができます。

containers are pure By default containers are pure, meaning they will not re-render when their props and state do not change (as determined by shallowEquals()). To disable this behavior pass options {pure: false} as the second argument to create().

containers are pure デフォルトのcontainerはpureであり、これはpropsやstateに変更がない時はre-renderされないことを意味しています(shallowEquals()によって決定された)。この振る舞いをできなくするには、create()メソッドの第二引数にオプションとして{pure: false}を渡します。

containers cannot access props By default containers are not able to access any props. This is both for performance reasons, and to ensure that containers are re-usable and props do not have to be threaded throughout a component tree. There are some valid situations in which you need to determine your state based on both props and a store’s state. In those situations pass options {withProps: true} as the second argument to create(). This will expose the components props as the second argument to calculateState().

containers cannot access props デフォルトのcontainerはどんなpropsにもアクセスできません。これはパフォーマンス的な理由と、containerはre-usableであり、porpsはcomponent treeの隅から隅までthreadされる必要はないということを保証するためです。いくつかのvalidなシチュエーションによっては、propsとstoreのstateに基づいてstateを決定する必要があるがあります。このような場合は、create()の第二引数にオプションとして{withProps: true}を渡します。これはcalculateState()の第二引数を通してcomponentのpropsを公開します。

If you are unable to utilize react classes most of this functionality is also mirrored in a mixin. import {Mixin} from ‘flux/utils’;

もし、Reactのclassを活用できない場合は、この機能のほとんどはmixinの中にもコピーがあります。 import {Mixin} from ‘flux/utils’;してください。

まとめ

ドキュメントを日本語に訳して実際に読んでみましたが、なんとなく内容は理解できたものの、これだけではすべてを掴みきれませんでした。実際にFlux Utilsを使って何か作ってみる必要があるかなと思います。

Flux Utilsには4つのクラスが用意されていますが、3つのStoreクラスは、Store > ReduceStore > MapStoreと継承関係にあるので、基本的にはStore群Containerの2つの役割と使い方を覚えることになると思います。その辺の使い方のポイントなどもまた後日まとめたいと思います。

[追記: 2016-01-30]早速超簡単なサンプルを作ってみました。

[追記: 2016-02-19]Flux Utilsの使い方をまとめました。

Flux Utilsに関して大変参考になる記事もあります。最後に紹介しておきます。

コメント一覧

  • 必須

コメント