ランサーズ等のサービスを開発・運用する中で得た知識やノウハウを紹介しています。

thumbnail

Labels:  JavaScript 投稿者:takepo

React × Redux で action 発行時に確認ダイアログを挟む middleware の実装例

pookチームのtakepoです。
今回は、React × Redux でstateを変更する時にダイアログ等で確認表示を挟みたいときの良い方法をご紹介します。
その場合の例として、「ユーザーの情報を更新するとき、更新しても良いかを一度確認するダイアログ表示する」といったことが挙げられます。

この方法を一言で言うと、
「Container側では変更処理をするactionのみ呼び出すようにする」
です。
サンプルを交えてご紹介します。

サンプル

データを更新する際に確認用のダイアログを表示し、「OK」を選択した場合に更新処理を行います。

Dialog Component

ダイアログのcomponentはこのような形で作成しておきます。
※今回はMaterial-UIを使用し、シンプルな作りにしています。

class Dialog extends Component {
    props: {
        openFlag: boolean;
        message: string;
        title: string;
        okClickHandler: Function;
    };

    renderDialogButtons(): React.Element<*> {
        return (
            <div>
                <RaisedButton
                    label="キャンセル"
                    onClick={/* ダイアログを閉じる処理 */}
                />
                <RaisedButton
                    label="OK"
                    onClick={this.props.okClickHandler}
                />
            </div>
        );
    }

    render() {
        return (
            <Dialog
                title={this.props.title}
                open={this.props.openFlag}
                actions={this.renderDialogButtons()}
            >
                {this.props.message}
            </Dialog>
        );
    }
}

export default Dialog;

更新処理をするactionを呼ぶContainer

変更処理をかけるactionを呼ぶ箇所はこのように書きます。
ここで注目したいポイントは、更新処理をするactionの第2引数にmeta情報としてダイアログのpropsに渡すmessageとtitleを入れておくことです。


const payload = {
 // 更新する情報
}
const meta = {
  dialogInfo: {
    title: '更新',
    message: '情報を更新しますがよろしいですか?',
  },
}

// 更新処理をかけるaction
this.props.actions.update(payload, meta);

middleware

更新処理をするactionでmetaとして入れ込んだダイアログの情報を元に、ダイアログを開くときに必要なpayloadを作成します。そして、ダイアログを開くためのactionをnext()に渡します。
ここで注目したいポイントは、payloadのokClickHandlerに本来の変更処理を行うactionを入れ込むことです。


export default (store: any) => (next: any) => (action: any) => {
    if (action.meta && action.meta.dialogInfo) {
        const payload = {
            ...action.meta.dialogInfo,
            okClickHandler: () => {
                // このままactionを渡すとまた確認ダイアログを挟んでしまうので、dialogInfoを削除しておく
                delete action.meta.dialogInfo;
                next(action);
            },
        };

        // open() はダイアログを開くaction
        return next(open(payload));
    }

    return next(action);
};

まとめ

省いてしまっている部分もありますが、流れとしてはこのようになります。
middlewareをうまく利用することで
「Container側では変更処理をするactionのみ呼び出すようにする」
ことができました。
これで更新処理を呼ぶ側をすっきり書くことができます!

ランサーズではサービスを成長させてくれるエンジニア、デザイナーを募集しています!
ご興味がある方は、以下URLよりご応募ください。

PHPエンジニア
Rubyエンジニア
フロントエンドエンジニア
インフラエンジニア
新卒エンジニア
その他採用情報

関連記事

thumbnail
SEOフレンドリーな無限スクロールの実装方法

飲み物は常温派のota(@purratto)です。自動販売機で常温のものも販売してくれればいいのになあ、と常々思っています。 ランサーズストアでSEOフレンドリーな無限スクロールをjQueryで実装しました。 サンプル向けに一部修正したコードを公開します。参考 …

thumbnail
react-redux v5.0.0でredux-form, material-uiを併用時、フォームの日本語入力が1文字目で確定される問題の対策

森です。しばらく日々のこまごまとした課題とその解決をブログに書き残しておくことにしました。 現象 redux-form の入力欄(Field)を material-ui(TextField)で作成しています。react-redux の v5.0.0-rc.1 …

チャットワークをもっと使いやすくする拡張機能を作った

こんにちはエンジニアの上野です。 2016年のAdventCalendar も残すところあと僅か! 12/5の投稿(githubのissue, pull request 検索をハックする!)に引き続き、今日はチャットワークの拡張プラグインのご紹介です。エンジニ …