Mixin 函数只在 render() 中有效

Mixin functions only work in render()

出于某种原因,我的代码中的 mixin 函数似乎只能在 render() 函数中正常工作。可能是我在 render() 之外没有以正确的方式调用它们,但它不应该完全相同吗?

这样一切正常(但我不能坚持这样做,因为我必须添加一些额外的东西来处理点击,同时不改变混合):

var Row = React.createClass({
    mixins: [someMixin]
    },

    render: function () {
        var clickHandler = null;
        var btn = null;

        if (firstCase) {
            clickHandler = this.order(this.props.name, this.props.else);
            btn = (<a href="" onClick={clickHandler}>Order</a>);
        } else if (secondCase) {
            clickHandler = this.noOrder(this.props.name, this.props.else);
            btn = (<a href="" onClick={clickHandler}>No order</a>);
        }
        return (
            <div>
                {btn}
            </div>
        );
    }
});

但是当我做了显而易见的事情并将 mixin 函数包含在另一个函数中以处理点击时 - 就像这样 - 一切都失败了,甚至 'test' 也没有在控制台中打印出来:

var Row = React.createClass({
    mixins: [someMixin]
    },

    handleOrderClick(type) {
        console.log('test');
        if (type == 'order') {
            this.order(this.props.name, this.props.else);
        } else if (type == 'no-order') {
            this.noOrder(this.props.name, this.props.else);
        }
    },

    render: function () {
        var clickHandler = null;
        var btn = null;

        if (firstCase) {
            clickHandler = this.handleOrderClick('order');
            btn = (<a href="" onClick={clickHandler}>Order</a>);
        } else if (secondCase) {
            clickHandler = this.handleOrderClick('no-order');
            btn = (<a href="" onClick={clickHandler}>No order</a>);
        }
        return (
            <div>
                {btn}
            </div>
        );
    }
});

编辑: ordernoOrder 函数如下所示:

order: function (name, else) {
    return function (event) {
        event.preventDefault();

        var term = name + '&&¤%' + else;
        Order.order(name, else, period, function (data) {

            if (term === (global || window).MAIN_NAME + '.' + (global || window).MAIN) {
                $(window).trigger('Name:update');
            }
        }.bind(this));
    }.bind(this);
},

noOrder: function (name, else) {
    return function (event) {
        event.preventDefault();

        if (!this.state.transferModalOpen) {
            this.toggleTransferModal();
        }
    }.bind(this);
}

为了在 handleOrderClick 中使用 this.setState,您必须在渲染方法中使用 bind 方法。因此 handleOrderClick 将变为:

handleOrderClick(type, event) {
    this.setState({foo: 'bar'});
    if (type == 'order') {
        this.order(this.props.name, this.props.else)(event);
    } else if (type == 'no-order') {
        this.noOrder(this.props.name, this.props.else)(event);
    }
},

并且您的渲染方法变为:

render: function () {
    var clickHandler = null;
    var btn = null;

    if (firstCase) {
        clickHandler = this.handleOrderClick.bind(this, 'order');
        btn = (<a href="" onClick={clickHandler}>Order</a>);
    } else if (secondCase) {
        clickHandler = this.handleOrderClick(this, 'no-order');
        btn = (<a href="" onClick={clickHandler}>No order</a>);
    }
    return (
        <div>
            {btn}
        </div>
    );
}

您会注意到 this.orderthis.noOrder 返回的函数不再由 handleOrderClick 返回,而是立即执行。这应该会提供您想要的效果。

我已将您示例中的代码放入 jsfiddle 中,现在它似乎可以正常工作。我不得不将道具 'else' 更改为 'alt' 因为 'else' 是一个保留字。为了简单起见,我还直接将 mixin 应用于 class。我已经简化了 ordernoOrder 函数,因为我无法访问 Order 对象,我们只对它们在正确的时间触发感兴趣。我还添加了第二个按钮,您可以单击它来翻转案例,以便呈现另一个按钮,从而使组件再次呈现。我添加了一个标签,显示上次按下按钮时调用了哪个函数。

作为参考,您可以找到有关绑定方法的更多信息here

希望对你有帮助^_^