使用 React.cloneElement 和 render prop 将 ref 传递给 class 组件
pass ref to a class component with React.cloneElement and render prop
我正在编写一个组件,根据 child 的 ref
处理一些内部 state
(与 child 的引用相关的鼠标事件例如)。
该组件使用 render-prop
将 state
的相关部分传递给它的 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
}
}
}
我正在编写一个组件,根据 child 的 ref
处理一些内部 state
(与 child 的引用相关的鼠标事件例如)。
该组件使用 render-prop
将 state
的相关部分传递给它的 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
}
}
}