tanaka's Programming Memo

プログラミングについてのメモ。

ReactでBootstrapのProgressBarを利用する

(メモのため、要点しか書いてません。)

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ファイルを灰色の枠にドラッグ&ドロップした時に、ファイルの読み込み状況を表示するのに利用