swi*_*_js 5 ref ecmascript-6 reactjs clone-element
我正在编写一个组件,该组件state
根据ref
其子对象处理一些内部事件(例如,与该子对象的ref相关的鼠标事件)。
该组件使用a render-prop
传递相关state
子对象的子元素,并ref
通过React.cloneElement
util 渲染带有附加子元素的子元素。
问题是,当子级是一个class
组件时,由于某种原因该子级ref
不可用,并且由于它是一种类型为react element的对象function
(我当然也将其克隆),因此我找不到一种渲染方法。
但是,如果子DOM
节点只是一个像a这样的节点div
,则它按预期运行。
我的解决方法是检查子类型,如果是子类型,function
则将克隆的元素包装成自己的子类型div
,如果只是dom节点,则照原样渲染。
但是,我不想用多余的东西包裹孩子,div
因为我不想添加不必要的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>
);
}
}
}
Run Code Online (Sandbox Code Playgroud)
用法:
class App extends Component {
render() {
return (
<div>
<Parent render={someValue => <div> {someValue}</div>} />
<Parent render={someValue => <Menu someValue={someValue} />} />
</div>
);
}
}
Run Code Online (Sandbox Code Playgroud)
当我像第一个示例一样渲染常规DOM节点时,它可以正常工作,而当我尝试渲染Menu
(作为一个class
组件)时,它如上所述无法工作。
我有几乎相同的问题。
我选择使用findDOMNode from ,你可以在react-external-click中react-dom
看到完整的解决方案。
尽管警告指出:
findDOMNode 是一个用于访问底层 DOM 节点的逃生舱口。在大多数情况下,不鼓励使用此逃生口,因为它会破坏组件抽象。
findDOMNode 仅适用于已安装的组件(即已放置在 DOM 中的组件)。如果您尝试在尚未安装的组件上调用此方法(例如在尚未创建的组件上调用 render() 中的 findDOMNode() ),则会抛出异常。
findDOMNode 不能用于功能组件。
我认为这是应对这一特殊挑战的更好解决方案。
它让您对消费者“透明”,同时能够定位DOM
.
好的,就在这里,抓住参考:
componentDidMount() {
this.ref = findDOMNode(this);
// some logic ...
}
Run Code Online (Sandbox Code Playgroud)
这就是我在没有自己的包装器的情况下使用渲染函数的方式:
render() {
const { children, render } = this.props;
const { clickedOutside } = this.state;
const renderingFunc = render || children;
if (typeof renderingFunc === 'function') {
return renderingFunc(clickedOutside);
} else {
return null
}
}
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
1021 次 |
最近记录: |