使用 React.cloneElement 和 render prop 将 ref 传递给 class 组件

pass ref to a class component with React.cloneElement and render prop

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

问题是当 child 是一个 class 组件时,由于某种原因 ref 不可用,我找不到将其呈现为它是一个类型为 function 的反应元素 object(当然是在我克隆它之后)。

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

我的work-around是检查child的类型,如果是function的类型我会用我自己的[=24=包裹克隆的元素],如果它只是一个 dom 节点,则按原样渲染。
但是,我不想用额外的 div 包装 child,因为我不想添加不必要的 DOM 节点。

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

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 组件)时它不起作用如上所述。

我遇到了几乎相同的问题。
我选择使用 findDOMNode from react-dom, you can see the full solution in react-external-click

尽管警告说明:

findDOMNode is an escape hatch used to access the underlying DOM node. In most cases, use of this escape hatch is discouraged because it pierces the component abstraction.

findDOMNode only works on mounted components (that is, components that have been placed in the DOM). If you try to call this on a component that has not been mounted yet (like calling findDOMNode() in render() on a component that has yet to be created) an exception will be thrown.

findDOMNode cannot be used on functional components.

我认为这是应对这一特殊挑战的更好解决方案。
它让您成为 "transparent" 消费者,同时能够针对 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
        }
    }
}