React:AppStore监听器必须是一个函数

Nic*_*vda 8 javascript reactjs

各位开发者!

感谢Egghead的教程,我一直在深入研究Flux/React.虽然我听说React正在移动,但是在遵循上述教程的同时,我在React库中遇到了一些变化.

到目前为止,我已经能够解决所有问题.现在,我遇到了关于商店的砖墙.正如教程所述,我正在制作一个购物车,用户可以在其中添加商品.没那么复杂.实际添加有效,但不会触发重新渲染.以下代码给出了添加的错误(完整代码也将在下面列出):

addChangeListener: function(callback) {
    this.on(CHANGE_EVENT, callback);
},
Run Code Online (Sandbox Code Playgroud)

这导致Uncaught TypeError:listener必须是一个函数.回调参数未定义(因此问题出在哪里).但是,因为我不仅仅是新的React的工作方式,我在查找问题方面遇到了麻烦.以下代码段是教程中的Store:

var AppStore = assign(EventEmitter.prototype, {

    emitChange: function() {
        this.emit(CHANGE_EVENT);
    },
    addChangeListener: function(callback) {
        this.on(CHANGE_EVENT, callback);
    },
    removeChangeListener: function(callback) {
        this.removeChangeListener(CHANGE_EVENT, callback);
    },
    getCart: function() {
        return _cartItems;
    },
    getCatalog: function() {
        return _catalog;
    },
    getCartTotals: function() {
        return _cartTotals();
    },
    dispatcherIndex: AppDispatcher.register(function (payload) {
        var action = payload.action;

        switch(action.actionType) {
            case AppConstants.ADD_ITEM:
                _addItem(payload.action.item);
                break;
            case AppConstants.REMOVE_ITEM:
                _removeItem(payload.action.index);
                break;
            case AppConstants.INCREASE_ITEM:
                _increaseItem(payload.action.index);
                break;
            case AppConstants.DECREASE_ITEM:
                _decreaseItem(payload.action.index);
                break;
        }

        AppStore.emitChange();

        return true;
    })
});
Run Code Online (Sandbox Code Playgroud)

请注意,这是来自Egghead.io教程的代码,我不是所有者(如果他们希望我将删除所述代码).

如果需要更多代码或解释,我将很乐意帮忙!

谢谢人们:)

编辑1:应该听取改变的组件,但不是:

var Cart = React.createClass({

    getInitialState: function() {
        return cartItems();
    },
    componentWillMount: function() {
        debugger;
        AppStore.addChangeListener(this.onChange);
    },
    componentDidMount: function() {
        debugger;
        AppStore.addChangeListener(this.handleChange);
    },
    handleChange: function() {
        debugger;
        this.forceUpdate();
    },
    _onChange: function() {
        debugger;
        this.setState(cartItems());
    },
    render: function() {
        var total = 0;
        var items = this.state.items.map(function (item, i) {
            var subtotal = item.cost * item.qty;
            total +=subtotal;
            return (
                <tr key={i}>
                    <td><RemoveFromCart index={i} /></td>
                    <td>{item.title}</td>
                    <td>{item.qty}</td>
                    <td>
                        <Increase index={i} />
                        <Decrease index={i} />
                    </td>
                    <td>${subtotal}</td>
                </tr>
            );
        });

        return (
            <table className="table table-hover">
                <thead>
                    <tr>
                        <th></th>
                        <th>Item</th>
                        <th>Qty</th>
                        <th></th>
                        <th>Subtotal</th>
                    </tr>
                </thead>
                <tbody>
                    {items}
                </tbody>
                <tfoot>
                    <tr>
                        <td colSpan="4" className="text-right">Total</td>
                        <td>${total}</td>
                    </tr>
                </tfoot>
            </table>
        );
    }
});
Run Code Online (Sandbox Code Playgroud)

chr*_*her 2

对我来说,听起来你已经解决了这个模式的大部分内容,但你有点困惑。您需要包括最后一步,这实际上是为您的组件订阅商店推出的事件。

this.emit(CHANGE_EVENT);
Run Code Online (Sandbox Code Playgroud)

这只会将一些东西推出去。如果没有人在监听,那么什么都不会改变,因此在您的组件中,您需要实际监听此事件。

对于一个组件来说,它可能看起来像这样:

React.createClass({
    componentDidMount: function() {
        // Called after react has rendered the HTML in the DOM.
        AppStore.addChangeListener(this.handleChange);
    },

    render: function() {
        return <div>{AppStore.someData}</div>
    },

    handleChange: function() {
        this.forceUpdate();
    }
});
Run Code Online (Sandbox Code Playgroud)

注意this.emit不应该打电话addChangeListener。它应该触发您使用该方法订阅的回调addChangeListener

潜在的改进

  • 需要注意的一件事是,尽管所有数据都在 中AppStore,但并非所有组件都会关心所有数据。例如,如果您有一个Name呈现用户名的组件,那么他们只关心NAME_CHANGE_EVENT. 他们不想每次发生小事就重新渲染。这是 React 不必要的处理,尽管 React 会推测没有任何变化并且不会更新 DOM。