【メモ】webpack.optimize.UglifyJsPluginでbuildしてもコメントが残っちゃうんだよねってとき
Reactアプリでリリースってなったとき、みんなやりたいのがjsファイルのminify。
webpackのドキュメント
に習い、webpack.config.jsで
plugins: [ new webpack.optimize.UglifyJsPlugin({ compress: { warnings: false } }) ]
を追加するも、ビルドしたソースにはコメントやスペースがもりもり残ってる。。😇
そんなときはjsのloaderにoptionを追加。
module: { loaders: [ { test: /\.js$/, loader: 'babel', query: { comments: false, compact: true }, exclude: /node_modules/, include: __dirname } ] }
babel-loaderのqueryに追加できるoption
無事、いい感じにminifyできました。
【メモ】React,Reduxのリファクタリングはじめの一歩
よくわからないままはじめ、まさに習うより慣れよで身につけつつある Reduxスキル。 最初のほうに作ったソースを見直すと、ある共通点に気がつきました。
無駄なstateが多い!
propsで受け取った値をわざわざコピーしてstateで保持してたりします。 変更される値はイベントハンドラの引数で受け取れるので、捕捉した値を propsのイベントで上位のコンポーネントに伝搬してしまえば、stateを 用意する必要がある箇所をぐっと減らすことができました。
//before:こういうかんじの記述が多かった handleChange(e) { const textValue = e.target.value this.setState({ textValue: textValue }, this.props.onChange(textValue)) } //after:丸投げでスッキリ handleChange(e) { this.props.onChange(e.target.value) }
変更フォームなど、propsで変更前、stateで変更後の値を保持して 比較したり、リセットボタンを押したら変更前の値に戻すとか、そういう 時以外はstateは最小限がソースが見やすいな、と思いました。
Reactで「Uncaught TypeError: Cannot read property 'props' of null」が出る
render(){ return <myCompornent onClick={this.handleClick}></myCompornent> }
ってやって、myCompornent側で
onClick(){ this.props.onClick() }
とかやると
Uncaught TypeError: Cannot read property 'props' of null
とエラーしてしまいます。
これは、
<myCompornent onClick={this.handleClick.bind(this)}></myCompornent>
とすることで回避できます。
これはes6の仕様です。es5で書かれたReactチュートリアルを写経すると発生しがちです。
きっちり写経したのにエラーしてしまう。。typoしてんのかな??
とか陥りがちなポイントです(というか陥った)。
React + React Bootstrap で、htmlでお知らせが書けるツールチップを使いたい
こういうやつが欲しい。
そこで
<Info message={message} />
こういうコンポーネントを作成したところ、messageに与えた文字列のhtmlタグがエスケープされて、そのまま出力されてしまう。
<Info message="Hello,<br/><br/><strong>world!!!!!!</strong>" /> // => Tooltipに「Hello,<br/><br/><strong>world!!!!!!</strong>」
それで、同じ壁にぶち当たってる人を探したら、いた。
なるほどArrayで渡せば良いらしい。
<Info message={[ "Hello,", <br/>, <br/>, <strong>world!!!!!!</strong>, <br/> ]}/>
これをInfoコンポーネントの中で this.props.message.join()
すればよいのか、と思いきや、
Warning: Each child in an array or iterator should have a unique "key" prop.
キーつけなさいよ!っておこられる。上のリンク先にもそうレスがありますね。
というわけでキーをつけます。
getMessage() { return this.props.message.map(function (m, index) { return <span key={index}>{m}</span> }) }
できあがったものはこちら。
import React, { PropTypes, Component } from 'react' import { Tooltip, OverlayTrigger } from 'react-bootstrap' import SHA256 from 'crypto-js/sha256' class Info extends Component { static propTypes = { message: PropTypes.array.isRequired, placement: PropTypes.string } getMessage() { return this.props.message.map(function (row, index) { return <span key={index}>{row}</span> }) } render() { const message = this.getMessage() const tooltip = <Tooltip id={SHA256(new Date()).toString()}>{message}</Tooltip> return ( <span className="info"> <OverlayTrigger placement={this.props.placement} overlay={tooltip}> <i className="fa fa-info-circle"></i> </OverlayTrigger> </span> ) } } export default Info
2016/08/10追記
パラメータのところ
<Info message={[ "Hello,", <br/>, <br/>, <strong>world!!!!!!</strong>, <br/> ]}/>
は、要はjsxの書式ならOKなので、
<Info message={[<span>Hello,<br/><br/><strong>world!!!!!!</strong><br/></span>]}/>
こっちのほうがスッキリしますね。
ESLintに「"$" is not defined no-undef」と怒られた
componentDidMount() { $.get('/data/hoge.json', function (result) { this.setState({ hogeList: result }); }.bind(this)); }
上記を定義したReactコンポーネントをESLintでテストすると怒られた。
error "$" is not defined no-undef
これは .eslintrcのenvにjqueryを追加することで解消する。
{ "env": { "jquery": true } }
参考にしたページ github.com
ReactのcomponentWillReceivePropsはPropTypes.funcの呼び出しも捕捉する
はまったのでメモ
以下のようなprops
とstate
を持つコンポーネント
static propTypes = { onChange: PropTypes.func.isRequired, // this.state.selectedItemListが変更されたときに発火 itemList: PropTypes.array.isRequired, // DBからとってきたマスター的なデータ }; constructor(props) { super(props); this.state = { selectedItemList: [] //選択状態を管理する }; }
this.props.itemList
がid
とname
で構成されたデータで、
そのデータにcheckboxを付与して取捨選択をさせる、というもの。
選択状態はthis.state.selectedItemList
で管理する。
ちなみに、this.props.itemList
には検索結果を与えるので、
変更がかかったらthis.state.selectedItemList
の選択状態は
都度初期化したい。
というわけで、初期化処理をcomponentWillReceiveProps
に
書いた。
componentWillReceiveProps(nextProps) { // this.props.itemList から選択状態を管理するthis.state.selectedItemList を生成 var selectedItemList = []; nextProps.itemList.map(function (item, index) { selectedItemList.splice(index, 0, { itemId: item.id, checked: false, //チェック状態 }); }); this.setState({ selectedItemList: selectedItemList }); }
選択状態の変更時は、this.props.onChange
に最新の
選択リストを与える。
handleChange(index, checked) { var selectedItemList = this.state.selectedItemList; selectedItemList[index].checked = checked; this.setState({selectedItemList: selectedItemList}, this.props.onChange(selectedItemList)); }
と、this.props.onChange(selectedItemList)
を
コールしたところでcomponentWillReceiveProps()
が走って
selectedItemList
が全部初期化されちゃった!orz
ので、componentWillReceiveProps
を以下に書き換えた。
componentWillReceiveProps(nextProps) { //this.props.itemListの変更がなければbreak if(this.props.itemList == nextProps.itemList){ return false; } // this.props.itemList から選択状態を管理するthis.state.selectedItemList を生成 var selectedItemList = []; nextProps.itemList.map(function (item, index) { selectedItemList.splice(index, 0, { itemId: item.id, checked: false, //チェック状態 }); }); this.setState({ selectedItemList: selectedItemList }); }
問題は解消されたけれど、なんだかな。 特定のpropsだけlistenできたらいいのにな。
IntelliJ IDEA に golang プラグインを入れる
JetBrains Plugin Repository :: Go
からzipファイルをダウンロード。
ここでは「Go-0.9.748.zip」をダウンロードしました。
Preferences -> Plugins -> Install plugin from disk...
でダウンロードした「Go-0.9.748.zip」を選択します。