2

最近、ReactJS を学び始めましたが、非同期呼び出しについて混乱しています。

ユーザー/パス フィールドとログイン ボタンを含むログイン ページがあるとします。コンポーネントは次のようになります。

var Login = React.createClass({

    getInitialState: function() {
        return {
            isLoggedIn: AuthStore.isLoggedIn()
        };
    },

    onLoginChange: function(loginState) {
        this.setState({
            isLoggedIn: loginState
        });
    },

    componentWillMount: function() {
        this.subscribe = AuthStore.listen(this.onLoginChange);
    },

    componentWillUnmount: function() {
        this.subscribe();
    },

    login: function(event) {
        event.preventDefault();
        var username = React.findDOMNode(this.refs.email).value;
        var password = React.findDOMNode(this.refs.password).value;
        AuthService.login(username, password).error(function(error) {
            console.log(error);
        });
    },

    render: function() {

        return (
                <form role="form">
                    <input type="text" ref="email" className="form-control" id="username" placeholder="Username" />
                    <input type="password" className="form-control" id="password" ref="password" placeholder="Password" />
                    <button type="submit" className="btn btn-default" onClick={this.login}>Submit</button>
                </form>
        );
    }
});

AuthService は次のようになります。

module.exports = {
    login: function(email, password) {
        return JQuery.post('/api/auth/local/', {
            email: email,
            password: password
        }).success(this.sync.bind(this));
    },

    sync: function(obj) {
        this.syncUser(obj.token);
    },

    syncUser: function(jwt) {
        return JQuery.ajax({
            url: '/api/users/me',
            type: "GET",
            headers: {
                Authorization: 'Bearer ' + jwt
            },
            dataType: "json"
        }).success(function(data) {
            AuthActions.syncUserData(data, jwt);
        });
    }
};

行動:

var AuthActions = Reflux.createActions([
  'loginSuccess',
  'logoutSuccess',
  'syncUserData'
]);

module.exports = AuthActions;

そして保存します:

var AuthStore = Reflux.createStore({
    listenables: [AuthActions],

    init: function() {
        this.user = null;
        this.jwt = null;
    },

    onSyncUserData: function(user, jwt) {
        console.log(user, jwt);
        this.user = user;
        this.jwt = jwt;
        localStorage.setItem(TOKEN_KEY, jwt);
        this.trigger(user);
    },

    isLoggedIn: function() {
        return !!this.user;
    },

    getUser: function() {
        return this.user;
    },

    getToken: function() {
        return this.jwt;
    }
});

したがって、ログインボタンをクリックすると、フローは次のようになります。

Component -> AuthService -> AuthActions -> AuthStore

で直接 AuthService を呼び出していAuthService.loginます。

私の質問は、私はそれを正しくやっているのですか?

アクション preEmit を使用して、次のことを行う必要があります。

var ProductAPI = require('./ProductAPI')
var ProductActions = Reflux.createActions({
  'load',
  'loadComplete',
  'loadError'
})

ProductActions.load.preEmit = function () {
     ProductAPI.load()
          .then(ProductActions.loadComplete)
          .catch(ProductActions.loadError)
}

問題は、preEmit がコンポーネントへのコールバックをより複雑にすることです。正しい方法を学び、ReactJS/Reflux スタックでバックエンド呼び出しを配置する場所を見つけたいと思います。

4

3 に答える 3

6

私もRefluxを使用しており、非同期呼び出しには別のアプローチを使用しています。

通常の Flux では、非同期呼び出しはアクションに入れられます。

ここに画像の説明を入力

しかし、Reflux では、非同期コードはストアで最もよく機能します (少なくとも私の謙虚な意見では)。

ここに画像の説明を入力

したがって、特にあなたの場合、コンポーネントによってトリガーされ、ログインプロセスを開始するストアによって処理される「ログイン」というアクションを作成します。ハンドシェークが終了すると、ストアはコンポーネントに新しい状態を設定し、ユーザーがログインしていることを知らせます。その間 ( whilethis.state.currentUser == nullなど)、コンポーネントは読み込みインジケーターを表示する場合があります。

于 2015-06-12T21:38:56.803 に答える
1

Reflux については、https://github.com/spoike/refluxjs#asynchronous-actionsを実際に確認する必要があります。

そこに記載されている内容の短いバージョンは次のとおりです。

  1. PreEmit フックを使用しないでください

  2. 非同期アクションを使用する

var MyActions = Reflux.createActions({
  "doThis" : { asyncResult: true },
  "doThat" : { asyncResult: true }
});

これにより、'makeRequest' アクションだけでなく、'doThis.completed'、'doThat.completed'、'doThis.failed'、'doThat.failed' アクションも作成されます。

  1. (オプションですが、推奨) promise を使用してアクションを呼び出す
MyActions.doThis.triggerPromise(myParam)
  .then(function() {
    // do something
    ...
    // call the 'completed' child
    MyActions.doThis.completed()
  }.bind(this))
  .catch(function(error) {
    // call failed action child
    MyActions.doThis.failed(error);
  });

私たちは最近、すべてのアクションと 'preEmit' フックをこのパターンに書き直して、結果と結果のコードを気に入っています。

于 2015-06-17T07:12:27.960 に答える
0

また、逆流との非同期がちょっと混乱していることもわかりました。Facebookからの生のフラックスを使用すると、次のようになります。

var ItemActions = {
  createItem: function (data) {
    $.post("/projects/" + data.project_id + "/items.json", { item: { title: data.title, project_id: data.project_id } }).done(function (itemResData) {
      AppDispatcher.handleViewAction({
        actionType: ItemConstants.ITEM_CREATE,
        item: itemResData
      });
    }).fail(function (jqXHR) {
      AppDispatcher.handleViewAction({
        actionType: ItemConstants.ITEM_CREATE_FAIL,
        errors: jqXHR.responseJSON.errors
      });
    });
  }
};

したがって、アクションは ajax リクエストを実行し、完了するとディスパッチャーを呼び出します。私は preEmit パターンもあまり得意ではなかったので、代わりにストアでハンドラーを使用します。

var Actions = Reflux.createActions([
  "fetchData"
]);

var Store = Reflux.createStore({
  listenables: [Actions],

  init() {
    this.listenTo(Actions.fetchData, this.fetchData);
  },

  fetchData() {
    $.get("http://api.com/thedata.json")
      .done((data) => {
        // do stuff
      });
  }
});

私はストアからそれを行うのは得意ではありませんが、還流がどのようにアクションを抽象化し、listenTo コールバックを一貫して起動するかを考えると、私はそれで問題ありません。コールバックデータをストアに設定する方法を説明するのは少し簡単です。それでも単方向のままです。

于 2015-06-12T15:53:29.253 に答える