React:从非所有者父组件调用函数

时间:2015-09-29 18:18:16

标签: javascript reactjs

我知道你可以将事件处理程序传递给由所有者组件显式呈现的子代,如下所示:

var Owner = React.createClass({
    eventHandler: function() {
        console.log("Interaction!");
    },
    render: function() {
        return (
            <div>
                <input onChange={this.eventHandler}/>
                <button onClick={this.eventHandler}/>
            </div>
        );
    }
});

但是如果我想将这些函数从父组件传递给它的嵌套this.props.children怎么办?

var Parent = React.createClass({
    eventHandler: function() {
        console.log("Interaction!");
    },
    render: function() {
        return (
            <span>
                {this.props.children}
            </span>
        );
    }
});
var Owner = React.createClass({
    render: function() {
        return (
            <div>
                <Parent>
                    <input onChange={whatDoIPutHere}/>
                    <button onClick={orDoIPutThisInTheParentIDK}/>
                </Parent>
             </div>
         );
});

通过这样做,我得到了一些工作:

var Parent = React.createClass({
    eventHandler: function() {
        console.log("Interaction!");
    },
    render: function() {
        var newChildren = this.props.children.map(child => {
            var newProps = {};
            if (child.type === 'input') {
                newProps.onChange = this.eventHandler;
            } else if (child.type === 'button') {
                newProps.onClick = this.eventHandler;
            }
            return React.cloneElement(child, newProps);
        });
        return (
            <span>
                {newChildren}
            </span>
        );
    }
});

但这要求我硬编码要查找的元素类型,以及将eventHandler传递给哪些元素。我希望能够在<Owner>组件中指定所有内容,并使<Parent>只是一个通用容器,它与eventHandler的调用方式无关。

有没有办法做到这一点?我希望避免使用getDOMNode()之类的任何变通办法,因为我预计此代码库可能会在未来与React Native共享。

2 个答案:

答案 0 :(得分:1)

为什么不只是概括不同的交互方法,只是将交互类型传递给处理程序?类似的东西:

var cloned = React.Children.map(this.props.children, function (c) {
    return React.cloneElement(c, {
      onChange: this.props.onInteraction.bind(this, 'change'),
      onClick: this.props.onInteraction.bind(this, 'click')
    });
}, this);

通过这种方式,您可以收到所有点击和更改的通知(其他类型的互动也可以添加到列表中,例如onKeyUponMouseMove等)

Link to jsbin example

答案 1 :(得分:0)

根据rossipedia的回答,我想出了这个:

var Parent = React.createClass({
    eventHandler: function() {
        console.log("Interaction!");
    },
    render: function() {
        var newChildren = React.Children.map(this.props.children, child => {
            var newProps = {};
            for (var i in child.props) {
                if (child.props[i] === "onInteraction") {
                    newProps[i] = this.eventHandler;
                }
            }
            return React.cloneElement(child, newProps);
        });
        return (
            <span>
                {newChildren}
            </span>
        );
    }
});

允许我这样做:

<Parent>
    <input onChange="onInteraction"/>
</Parent>

不是超级优雅,但它有效。一旦React 0.14命中,可能能够通过基于父的上下文更好地找出更好的东西。