読者です 読者をやめる 読者になる 読者になる
一人もくもく会 α verでサービス開始しました。

ReactにReduxを組み合わせると何が楽なのか

JavaScript React program

React + Reduxを使うとどうメリットがあるかというと、色々とあるとは思う。 ただ、どう楽になるのかというのに焦点をおいてみる。

Reactのみの例

下記のようなコンポーネント構成のアプリケーションを作成するとする。

  • コンテナ : App
    • ヘッダ : Header
      • ログインボタン : Login(ログイン時はユーザー名表示)
    • コンテンツ : Contents

Reactのみだと関連箇所は下記のようなjsxになるだろう。

App

<div>
    <Header
        user={this.state.user}
        onLogined={this.onLogined}
        />
    <Contents
        user={this.state.user}
        contents={this.state.contents}
        />
</div>

Header

<div>
    <Login
        user={this.props.user}
        onLogined={this.props.onLogined}
        />
</div>

Login

handleLoginでサーバーへのログインリクエストを行い成功したらthis.props.onLoginedを呼び出す。

<div>
    <button onClick={this.handleLogin}>ログイン</button>
</div>

共通で使用される値は一番上の階層で扱うのが望ましいので、 見ての通りuserとonLoginedをひたすらプロパティで引き継ぎまくる事になってしまう。 Reactの良さを理解してもこのあたりでうんざりしてくる。

React + Reduxにすると

プロパティでの指定が不要になる。 簡単なログアウトボタンの例は下記の様になる。 (actionやreducer等の細かい部分の解説は省く)

import React from 'react';
import { connect } from 'react-redux';
import request from 'superagent';
import { setUser } from '../../actions/main';

function mapDispatchToProps(dispatch) {
    return {
        handleLogin: (user) => dispatch(setUser(user)),
    };
}

class Logout extends React.Component {

    handleSubmit(e) {
        request.post('/logout')
            .end((err, res) => {
                if (!err) {
                    this.props.handleLogin(null);
                }
            });

    }

    render() {
        return (
            <button onClick={this.handleSubmit}>ログアウト</button>
        );
    }
}

export default connect((state) => state, mapDispatchToProps)(Logout);

上記のようにコールバックのプロパティもその場で決められる。 また、下記のように、ヘッダー側のユーザー情報表示もuserを引き継がなくても取得できる。 (connectにより勝手にpropsに入っている)

import React from 'react';
import { connect } from 'react-redux';
import Login from './login';
import Logout from './logout';

import { setUser } from '../../actions/main';

class Header extends React.Component {

    renderUser() {
        if (this.props.user == null) {
            return <Login />;
        }
        return (
                    <div>
                        こんにちは{this.props.user.name}さん
                        <Logout />
                    </div>
                );
    }

    render() {
        const user = this.renderUser();

        return (
            <div>
                <h1>タイトル</h1>
                {user}
            </div>
        );
    }
}

export default connect((state) => state)(Header);

まとめ

どんどん細かくコンポーネントするのがよい、ということのはずだがそれをデメリットに変えてしまう自己矛盾したプロパティの仕組み。 Reduxによってそれが解消され使い勝手の良い物になる。 極小アプリケーションでない限りはほぼ必須であると思われる。