【问题标题】:pass ref to a class component with React.cloneElement and render prop使用 React.cloneElement 和 render prop 将 ref 传递给类组件
【发布时间】:2018-05-06 11:46:44
【问题描述】:

我正在编写一个组件,根据它的孩子的 ref 处理一些内部 state(例如,与该孩子的 ref 相关的鼠标事件)。
该组件使用render-propstate 的相关部分传递给它的孩子,并通过React.cloneElement 实用程序附加ref 渲染孩子。

问题是当孩子是class 组件时,由于某种原因ref 不可用,我找不到渲染它的方法,因为它是一个具有@ 类型的反应元素对象987654329@(当然是在我克隆它之后)。

但如果子节点只是一个DOM 节点,例如div,它会按预期工作。

我的解决方法是检查子节点的类型,如果它是function 的类型,我将用我自己的div 包装克隆的元素,如果它只是一个 dom 节点,则按原样渲染.
但是,我不想用额外的div 包裹孩子,因为我不想添加不必要的DOM 节点。

这是一个基本代码示例,为简洁起见删除了大部分代码:
父组件:

class Parent extends Component {

    attachRef = node => {
        this.ref = node;
    }

    render() {
        const { render } = this.props;
        const { someValue } = this.state;
        const Child = render(someValue);
        const WithRef = React.cloneElement(Child, {
            ref: this.attachRef
        });
        if (typeof WithRef.type === 'string') { // node element
            return WithRef;
        }
        else if (typeof WithRef.type === 'function') {
            // this is a react element object.. not sure how to render it
            // return ?
        } else {
            // need to find a way to render without a wrapping div
            return (
                <div ref={this.attachRef}>{Child}</div>
            );
        }
    }
}

用法:

class App extends Component {
    render() {
        return (
            <div>
                <Parent render={someValue => <div> {someValue}</div>} />
                <Parent render={someValue => <Menu someValue={someValue} />} />
            </div>
        );
    }
}

当我像第一个示例一样渲染常规 DOM 节点时,它可以正常工作,当我尝试渲染 Menu(这是一个 class 组件)时,它不会像上面提到的那样工作。

【问题讨论】:

  • Menu 是 SFC(功能组件)吗,您介意分享您的 Menu 组件吗?
  • 我对 SFC 没有任何问题,因为它们将返回 DOM 节点。 Menu 实际上可以是任何东西,我真的不知道,因为我的组件将是某种库。在示例中,Menu 是一个 class 组件,正如我所提到的,这就是事情进展的地方。
  • 需要注意的是 ref 不能用于指向功能组件,因为它没有实例。
  • 从上面的 sn-ps 来看,除了创建 this.ref 引用之外,很难判断 ref 是如何实际使用的,您能否更具体地说明您的意思 ref is not available

标签: reactjs ecmascript-6 ref clone-element


【解决方案1】:

我遇到了几乎相同的问题。
我从react-dom 中选择使用findDOMNode,你可以看到完整的解决方案in react-external-click

虽然警告说明:

findDOMNode 是一个用于访问底层 DOM 节点的逃生舱口。 在大多数情况下,不鼓励使用此逃生舱口,因为它 穿透组件抽象。

findDOMNode 仅适用于已安装的组件(即, 已放置在 DOM 中)。如果您尝试在组件上调用它 尚未安装的(例如在 render() 中调用 findDOMNode() 在尚未创建的组件上)将出现异常 扔了。

findDOMNode 不能用于功能组件。

我认为这是应对这一特殊挑战的更好解决方案。
它让您对消费者“透明”,同时能够定位 DOM 中的组件。

好了,抓到裁判了:

componentDidMount() {
    this.ref = findDOMNode(this);
    // some logic ...
}

这就是我使用没有自己的包装器的渲染函数的方式:

render() {
        const { children, render } = this.props;
        const { clickedOutside } = this.state;
        const renderingFunc = render || children;

        if (typeof renderingFunc === 'function') {
            return renderingFunc(clickedOutside);
        } else {
            return null
        }
    }
}

【讨论】:

    猜你喜欢
    • 2020-05-22
    • 1970-01-01
    • 2021-04-09
    • 1970-01-01
    • 2019-07-25
    • 2021-05-28
    • 1970-01-01
    • 2016-12-16
    • 2021-05-12
    相关资源
    最近更新 更多