(メモのため、要点しか書いてません。)
ReactでBootstrapのProgressBarを使って、ファイルの読み込み状況を表示しようとしたところ、バーが全然伸びない症状が発生しました。
原因
ファイルの読み込みなどの重い処理を実行中は、BootstrapのProgressBarのアニメが更新されないことがあるようです。そのため、0%からそのまま読み込みに合わせてProgressBarの幅を変更しても、バーが十分に伸びません。
解決策
ProgressBarは、最初に設定した幅はアニメせずにすぐに表示されます。そこで、ProgressBarのkey属性を更新するたびに変更してコンポーネントが差し替わるようにします。
それだけでうまく動きますが、少しでもアニメできないかということで、コンポーネントを描画する時は、ひとつ前の長さを設定して、コンポーネントの更新後に目的の長さを設定するようにしてみました。効果はいまひとつ分かりませんが・・・。
ソースコード抜粋
ProgressBarを呼び出すコンポーネントの一部
render: function() { return ( <div className='container'> <ProgressBar nowIndex={this.state.nowIndex} fileCount={this.files.length} /> </div> ); } });
- this.state.nowIndexに、現在読み込んでいるファイルのインデックス
- this.filesは、読み込むファイルオブジェクトが入っている配列
- ファイルを読み込むごとにnowIndexのstateを更新することで、コンポーネントが描画されるようにしている
プログレスバー用のReactClass例
var React = require('react/dist/react.min'); module.exports = React.createClass({ /** プロパティの指定*/ propTypes: { nowIndex: React.PropTypes.number.isRequired, fileCount: React.PropTypes.number.isRequired }, /** 前回のパーセンテージ*/ lastPercent: 0, /** パーセンテージ*/ percent: 0, /** コンポーネント更新後に目的のパーセントを設定*/ componentDidUpdate: function() { $('#pgbar').css('width', this.percent+'%'); }, /** 描画*/ render: function() { var newper = 0; // 進捗を更新する newper = Math.round((this.props.nowIndex+1)*100/this.props.fileCount); if (newper > this.percent) { this.lastPercent = this.percent; } else { this.lastPercent = newper; } this.percent = newper; // 開始幅を設定 var styles = { width: this.lastPercent+"%" }; return ( <div className='progress'> <div className='progress-bar progress-bar-striped active' id='pgbar' key={'pgbar'+newper} role='progressbar' aria-valuenow={newper} aria-valuemin='0' aria-valuemax='100' style={styles} >{newper+'%'} </div> </div> ); } });
- Reactをnpmでインストールしている前提
利用例
- こちら写真のEXIF取り出しのページで利用
- 複数のJPEGファイルを灰色の枠にドラッグ&ドロップした時に、ファイルの読み込み状況を表示するのに利用