【问题标题】:Flux/ReactJS leveraging spinJS in componentFlux/ReactJS 在组件中利用 spinJS
【发布时间】:2015-11-15 20:16:36
【问题描述】:

我正在使用带有 reactjs 的通量架构。我正在尝试实现对显示 spinjs 微调器的控制。

这是我使用微调器的组件视图:

var ItemListing = React.createClass({
    render: function(){

        if (this.state.loading === true) { 
            return (
                <div className="pill-pane active item-list-pane">
                        <LoadSpin />
                </div>
            )
        }

        // .. more non-related logic here

        return (
            <div className="pill-pane active item-list-pane">
                { items }
                <Paginator
                    paginationClickHandler={ this.paginationClickHandler }
                    offset={ offset }
                    limit={ limit }
                    store={ AppStore }
                />
            </div>
        );
    },

    getInitialState: function(){
        return {
            items: AppStore.getAssetDetails().assetList
        };
    },

    componentWillMount: function(){
        AppStore.addChangeListener(this.changeHandler);
        AppStore.addChangeListener(this.toggleActivity);
    },

    componentDidMount: function(){
        this.setState({loading: false});
        AppActions.queryAssets();
    },

    toggleActivity: function() {
        this.setState({loading: true});
    }
});

如 componentWillMount 所示,我添加了 this.toggleActivity,它最终将加载状态设置为 true。然后在 componentDidMount 我将加载状态设置为 false。但由于某种原因,我的微调器仍然无限期地旋转。也就是说,当这样布局时,它永远不会被设置为 false。我该如何更改它以使其更改为 false?

编辑 - 按要求添加 AppStore.js:

"use strict";

var AppDispatcher = require('../AppDispatcher');
var assetConstants = require('../constants/AssetConstants');
var EventEmitter = require('events').EventEmitter;

var CHANGE_EVENT = 'assetChange';

// Application State
var _assetDetails = {
    assetList: [],
    requestStatus: undefined,
    totalCount: 0
};

var _queryProgress;

var AppStore = $.extend({}, EventEmitter.prototype, {
    emitChange: function(){
        this.emit(CHANGE_EVENT);
    },

    addChangeListener: function(callback){
        this.on(CHANGE_EVENT, callback);
    },

    removeChangeListener: function(callback){
        this.removeListener(CHANGE_EVENT, callback);
    },

    getTotalCount: function(){
        if(_assetDetails.meta){
            return _assetDetails.meta.total_count;
        }

        return 0;
    },

    getAssetDetails: function(){
        return _assetDetails;
    },

    getRequestStatus: function(){
        return _assetDetails.requestStatus;
    },

    getQueryProgress: function(){
        return _queryProgress;
    },

    dispatcherIndex: AppDispatcher.register(function(payload){
        var action = payload.action.actionType;

        if(payload.source === "ASSET_ACTION"){
            switch(action){ // eslint-disable-line default-case
                case assetConstants.QUERY_ASSETS:
                    _assetDetails = payload.action.assetDetails;
                    break;

                case assetConstants.QUERY_PROGRESS:
                    _queryProgress = payload.action.progress;
                    break;
            }

            AppStore.emitChange();

            _assetDetails.requestStatus = undefined;
        }
        return true;
    })
});

module.exports = AppStore;

重新编辑添加的 AppActions.js:

"use strict";
var assetConstants = require('../constants/AssetConstants');
var AppDispatcher = require('../AppDispatcher');
var config = require('../../config');
var ITEM_V2_MAP = require('./apiRemapping').ITEM_V2_MAP;
var getRemappedAssets = require('./apiRemapping').getRemappedAssets;

var AssetActions = {
    queryAssets: function(filters){
        var assetDetails;

        $.ajax({
            method: "GET",
            url: config.endpoints.itemAPIV2,
            contentType: "application/json",
            dataType: "json",
            data: filters,
            beforeSend: function(){
                AppDispatcher.handleAssetAction({
                    actionType: assetConstants.QUERY_PROGRESS,
                    progress: "querying"
                });
            },
            success: function(data) {
                var remappedAssets = getRemappedAssets(
                    data.objects, ITEM_V2_MAP
                );

                assetDetails = {
                    assetList: remappedAssets,
                    currentFilters: filters,
                    meta: data.meta
                };
            },
            error: function() {
                assetDetails = {
                    assetList: [],
                    totalCount: 0
                };
            },
            complete: function(data) {
                assetDetails.requestStatus = data.status;

                AppDispatcher.handleAssetAction({
                    actionType: assetConstants.QUERY_ASSETS,
                    assetDetails: assetDetails
                });

                AppDispatcher.handleAssetAction({
                    actionType: assetConstants.QUERY_PROGRESS,
                    progress: "finished querying"
                });
            }
        });
    }
};

module.exports = AssetActions;

【问题讨论】:

  • 你在做服务器端渲染是偶然的吗?
  • 我的主要商店中有 ajax 操作。然后我从所说的商店拉出来。这就是服务器端渲染的意思吗?
  • 不,我的意思是在服务器上实际运行 render 等,然后将 HTML 提供给客户端。您能否偶然向我们展示您的AppStore 代码?
  • @MatthewHerbst 我相信我正在使用客户端渲染。我已经更新了问题以包括 AppStore
  • AppStore.addChangeListener(this.toggleActivity); 你永远不会(afaik)删除这个监听器,所以每次都会调用它并将 loading 设置为 true。

标签: javascript reactjs flux


【解决方案1】:

AppStore.addChangeListener(this.toggleActivity); 放在componentWillUnmount() 生命周期中应该可以解决问题。

【讨论】:

  • 我试过这个,但它似乎不起作用。我还尝试在componentWillUnmount 中添加this.setState({loading: false});,但它仍然不起作用。
  • AppActions.queryAssets(); 是否有可能触发一个导致toggleActivity 再次执行的事件?此外,在 Flux 中,您不应直接从应用程序修改状态,而应使用商店。
  • 不,AppActions.queryAssets(); 除了执行 AJAX 调用之外没有做任何事情。我在我原来的问题中提供了它。是的,我同意它应该在商店中,但是鉴于 ReactJs 生命周期,它应该按原样工作,但不是。
猜你喜欢
  • 2016-05-06
  • 2017-06-14
  • 2015-08-25
  • 2015-04-19
  • 2017-02-22
  • 2014-12-09
  • 2015-03-31
  • 2015-08-02
  • 2017-09-27
相关资源
最近更新 更多