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

React: Call a function from a non-owner parent component

本文关键字:组件 调用 函数 所有者 React      更新时间:2023-09-26

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

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传递给哪个prop。我希望能够在<Owner>组件中指定所有这些,并且<Parent>只是一个通用容器,它不知道它的eventHandler是如何被调用的。

有什么办法可以做到吗?我想避免像getDOMNode()这样的变通方法,因为我希望这个代码库将来可能会与React Native共享。

为什么不泛化不同的交互方法,并将交互类型传递回处理程序呢?比如:

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);

这样你就可以得到所有点击和更改的通知(其他类型的交互也可以添加到列表中,如onKeyUp, onMouseMove等)

链接到jsbin示例

根据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命中。