Javascript React forwardRef HoC不提供对容器元素的引用
我正在尝试为一个关闭元素在其空间外单击构建一个通用的HOC(通用的外部关闭解决方案) 在我看来,这可以通过forwardRef和HOC实现,尽管在官方文档中有一个例子,但我似乎无法正确实现 因此,我希望我的HOC创建对组件容器的引用。它是包装的,因为它有处理程序来跟踪点击并对其进行操作。例如,假设我们有一个通用的下拉组件,人们会期望我可以在该组件区域之外的任何单击上关闭它 我目前拥有的代码:Javascript React forwardRef HoC不提供对容器元素的引用,javascript,reactjs,higher-order-components,Javascript,Reactjs,Higher Order Components,我正在尝试为一个关闭元素在其空间外单击构建一个通用的HOC(通用的外部关闭解决方案) 在我看来,这可以通过forwardRef和HOC实现,尽管在官方文档中有一个例子,但我似乎无法正确实现 因此,我希望我的HOC创建对组件容器的引用。它是包装的,因为它有处理程序来跟踪点击并对其进行操作。例如,假设我们有一个通用的下拉组件,人们会期望我可以在该组件区域之外的任何单击上关闭它 我目前拥有的代码: import React from 'react'; function withClose(Compo
import React from 'react';
function withClose(Component) {
class ClickContainer extends React.Component {
constructor() {
super();
this.handleClose = this.handleClose.bind(this);
}
componentDidMount() {
document.addEventListener('click', this.handleClose);
}
componentWillUnmount() {
document.removeEventListener('click', this.handleClose);
}
handleClose(e) {
// I expect having here context of container of wrapped component to do something like
const { forwardedRef } = this.props; // <- I expect having context in forwardedRef variable
}
render() {
const { forwardedRef, ...rest } = this.props;
return <Component ref={forwardedRef} {...rest} />;
}
}
return React.forwardRef((props, ref) => {
return <ClickContainer {...props} forwardedRef={ref} />;
});
}
export default withClose;
从“React”导入React;
带关闭的函数(组件){
类ClickContainer.Component{
构造函数(){
超级();
this.handleClose=this.handleClose.bind(this);
}
componentDidMount(){
document.addEventListener('click',this.handleClose);
}
组件将卸载(){
document.removeEventListener('click',this.handleClose);
}
手环(e){
//在这里,我希望包装组件的容器上下文可以做如下事情
const{forwardedRef}=this.props;//{
返回;
});
}
用close导出默认值;
我在这里遗漏了什么?我不能让它工作,我只得到包装组件的上下文,而不是元素本身
非常感谢!几天前我实现了同样的功能。 我想要一个处理
onClickoutside
我希望该组件在每次单击时检查子对象是否单击,以及是否调用子对象上的函数
这就是我的解决方案:
import React from 'react';
export default function withClickOutside(WrappedComponent) {
class WithClickOutside extends WrappedComponent {
constructor(props) {
super(props);
this.handleClickOutside = this.handleClickOutside.bind(this);
this.wrappedElement = React.createRef();
}
componentDidMount() {
document.addEventListener('click', this.handleClickOutside, true);
}
componentWillUnmount() {
document.removeEventListener('click', this.handleClickOutside, true);
}
handleClickOutside(event) {
if (event.type !== 'click') return;
if (!this.wrappedElement.current) {
throw new Error(`No ref for element ${WrappedComponent.name}. Please create ref when using withClickOutside`);
}
if (!this.wrappedElement.current.contains(event.target)) {
if (!this.onClickOutside) {
throw new Error(`${WrappedComponent.name} does not implement onClickOutside function. Please create onClickOutside function when using withClickOutside`);
}
this.onClickOutside(event);
}
}
render() {
const wrapped = super.render();
const element = React.cloneElement(
wrapped,
{ ref: this.wrappedElement },
);
return element;
}
}
return WithClickOutside;
}
然后,您包装的组件必须实现一个名为
onClickOutside
Ref的函数,并将其传递给元素
结帐
假定
export const Popup = (props,) => {
const { name, forwardRef } = props;
return (
<div ref={forwardRef}> // You need to pass it down from props
{name}
</div>
)
}
export const Popup=(道具,)=>{
const{name,forwardRef}=props;
返回(
//你需要把它从道具上传下来
{name}
)
}
以及特别组织
export function withClose(Component) {
class ClickContainer extends React.Component {
constructor() {
super();
this.handleClose = this.handleClose.bind(this);
}
componentDidMount() {
document.addEventListener('click', this.handleClose);
}
componentWillUnmount() {
document.removeEventListener('click', this.handleClose);
}
handleClose(e) {
const { forwardRef } = this.props;
console.log(forwardRef);
}
render() {
const { forwardRef, ...rest } = this.props;
return <Component forwardRef={forwardRef} {...rest} />;
}
}
return React.forwardRef((props, ref) => {
return <ClickContainer {...props} forwardRef={ref} />;
});
}
带关闭的导出功能(组件){
类ClickContainer.Component{
构造函数(){
超级();
this.handleClose=this.handleClose.bind(this);
}
componentDidMount(){
document.addEventListener('click',this.handleClose);
}
组件将卸载(){
document.removeEventListener('click',this.handleClose);
}
handleClose(e){
const{forwardRef}=this.props;
控制台日志(forwardRef);
}
render(){
const{forwardRef,…rest}=this.props;
返回;
}
}
return React.forwardRef((道具,ref)=>{
返回;
});
}
期待
const CloseablePopup = withClose(Popup);
class App extends Component {
popupRef = React.createRef();
render() {
return (<CloseablePopup ref={popupRef} name="Closable Popup" />);
}
}
const CloseablePopup=withClose(Popup);
类应用程序扩展组件{
popupRef=React.createRef();
render(){
返回();
}
}
什么是this.containerRef
?您需要将this.props.forwardedRef
传递给element@Orar是的,很抱歉,这只是我尝试过的遗留问题,我将其更改为正确的代码…基本上这是正确的解决方案,我缺少在容器中创建ref…虽然这并不能完全回答我的问题。你认为呢知道有没有可能在不提供父级引用的情况下实现它?这要求我在多个位置定义引用,而不是让它自己处理所有事情。ThanksHOC在不由包装组件处理的情况下传递ref可能会导致错误,如果包装组件是函数。如果包装组件是类,ref只能访问类的实例,而不能访问容器元素。阅读这里,这是一个解决方案,它可以工作,但有点粗糙。如果可能的话,我想在没有cloneElement的情况下实现它。你能想到其他实现方案吗?我知道它的abit hack,但出于某种原因采用了这个解决方案n尝试在没有克隆元素的情况下使其工作,并获得对已包装组件的引用,但没有工作。好的是,您不需要在已包装组件中处理引用,因此保存了一些代码和错误,而忘记了添加它们