#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で展開する方法です。