React.js, Flux, CofeeScriptで試作したメモ


React.js, Flux, CofeeScriptで試作したメモ

環境

  • reactjs
  • Fluxxor
  • CoffeeScript
  • react-bootstrap

JSXのCompile

最初CoffeeScriptでReactJS環境を構築したメモ
に従って、coffee-reactを使用して見たが、
素のJsxコンパイラではエラーにならない所がエラーになってしまったので、
JsxファイルでComponentの記述のみ行い、CoffeeScriptは別ファイルで
開発する事にした。
Flux,Action,Store,HandlerはCoffeeScriptファイルに記述する。

$w.flux = new Fluxxor.Flux()
$w.commonStore=new $c.CommonStore;
$w.flux.addStore("COMMON",$w.commonStore)
$w.flux.addActions($c.actions)
$w.FluxMixin = Fluxxor.FluxMixin(React)
$w.StoreWatchMixin = Fluxxor.StoreWatchMixin
$w.common=$w.flux.stores.COMMON

StateとPropについて

Stateは最上位のComponentである Applicationにのみ定義、
下位のComponentにはPropで伝達する。なお $w.fluxは、
Applicationにflux propとして定義する。

React.render(<$w.Application flux={$w.flux}/>, document.getElementById('content'));

Global変数の使用

今回は、参照しやすさを優先して下記のGlobal変数を使用した。

  • $c - 共通Coffee Fileで使用するGlobal変数
  • $w - 画面単位のCoffee Fileで使用するGlobal変数

以下に例を示す

  • $c.constants - 共通で使うDispach 定数
  • $c.actions - 共通で使うAction
  • $c.CommonStore - 共通で使うStore
  • $c.XXX - 共通で使う関数等
  • $w.flux - Fluxxorのインスタンス
  • $w.common - CommonStoreのインスタンス
  • $w.app - 最上位Compnent Applicationのインスタンス

onChange,onClick等のHandlerについて。

CoffeeScriptファイルに、Global定義

以下に例を示す

  • $w.handleChange
  • $w.handleClick

各Componentは、Name Propertyで例えば"search#loginId"と指定した物を
共通のHandlerで、この例であれば state.search.loginIdの値をonChange
eventにより、更新する。(setState functionで)

stateを階層構造にする事により、Form単位のデータの取得が一括で出来る。

onClickの場合は、Name Property判断して当該処理を行う。

尚一部 Componentで Name Propertyが無い場合はIDで行う。

getStateFromFlux

onChange eventでStoreからstateにCopyするFunctionは以下の様に記述する。

Storeでは、this.data以下にstateにCopyされる変数を置く。

lodashのcloneDeepを使用する。

getStateFromFlux: function() {
return {
common:_.cloneDeep($w.common.data)
};
},

Storeの管理するstateとApplicationの管理するstateの分離

上記の様に使い分けています。

Tableで Storeで Ajaxで取り込んだものを Inlineで編集する場合は、
両方に該当してしまいますので、Storeで取り込んだものをchange以外のevent
を emitして、Store管理からApplication管理にCopyしています。

$w.rcdStore.on("rcdComplete_login", ->
rcdLogin=_.cloneDeep($w.app.state.rcd.login)
loginTemp={
login:$w.app.state.login
}
loginTemp.login.rcds=rcdLogin.rcds
loginTemp.form=rcdLogin.rcd
loginTemp.login.selRow=rcdLogin.selRow
$w.app.setState(loginTemp)
)

react-bootstrapを使用していて、InputのDomNodeが取れなかった場合

refに値をsetして、this.refs["refの値"].getDOMNode() で取れると思ったのですが、
react-bootstrapのInput componentでは取れませんでした。
素の<input> componentを使用する必要がありました。

その後調べた所、getInputDOMNode()というHelper Methodを使用すれば良いそうです。

動的に複数行のレンダリングを行う場合。

下記のSelect componentを参考にして下さい。

var b = ReactBootstrap;
$c.SelectOption = React.createClass({
handleChange: function (e) {
this.props.onChange(e);
},
render: function() {
var options = this.props.options.map(function(opt, i){
return <option key={i} value={opt.value} label={opt.label}>{opt.label}</option>;
}, this);
return (
<b.Input type="select" label=''
defaultValue={this.props.defaultValue}
multiple={this.props.multiple}
name={this.props.name} style={this.props.style}
onChange={this.handleChange}
>
{options}
</b.Input>
);
}
});

mapでArrayに入れ、それをrenderで展開する方法です。