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

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のみ呼び出すようにする」
ことができました。
これで更新処理を呼ぶ側をすっきり書くことができます!

関連記事

thumbnail
Webpack で git 管理してもよいような環境ごとに値の異なる定数を設定する方法

森です。仕事でのちょっとしたコミットをブログ記事化するシリーズです。今日は Webpack の話題です。 課題 環境ごとに値の異なる定数として、git で管理できるものと git で管理すべきではないものがあります。後者は dotenv と Webpack の …

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

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

ES6 + React.js + Redux で作るチャットシステム

アプリケーションエンジニアのyutakaです。 先日ランサーズのメッセージ機能をリニューアルしました。 ランサーズのメッセージ機能はリアルタイムのチャット形式で他のユーザーさんとコミュニケーションがとれる機能となっています。 リニューアルに伴って、フロントエン …