Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React forwardRef HoC not giving reference to container element

Tags:

I am trying to build a generic HOC for a closing element on click of outside its space(generic close on outside solution).

As I see it ,this could be achieved with forwardRef and HOC implementation and although there is an example in official docs I cannot seem to get it right.

So I want my HOC to create a reference to the container of component. It is wrapping because it has handlers to track clicks and act upon them. For instance, lets say we have a generic Dropdown component, one would expect that I can close it on any click outside the area of this component.

The code I currently have:

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;

What am I missing here? I cannot make it work, I only get context of wrapped component not the element itself.

Thanks a bunch!

like image 937
Mario Nikolaus Avatar asked Dec 19 '18 10:12

Mario Nikolaus


People also ask

Is forwardRef a hoc?

forwardRef() which means we have to apply the HOC before React.

How do you pass forwardRef?

The only way to pass a ref to a function component is using forwardRef. When using forwardRef, you can simply pass the ref to a DOM element, so the parent can access it like in example 1, or you could create an object with fields and methods using the useImperativeHandle hook, which would be similar to eample 2.

Can we pass ref to child component React?

React forwardRef is a method that allows parent components pass down (i.e., “forward”) refs to their children. Using forwardRef in React gives the child component a reference to a DOM element created by its parent component. This then allows the child to read and modify that element anywhere it is being used.


1 Answers

Ref should be passed down to the element

Checkout https://codesandbox.io/s/7yzoqm747x

Assuming

export const Popup = (props,) => {
  const { name, forwardRef } = props;
  return (
   <div ref={forwardRef}>  // You need to pass it down from props
     {name}
   </div>
  )
}

And the HOC

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} />;
  });
}

And expect

 const CloseablePopup = withClose(Popup);

  class App extends Component {
    popupRef = React.createRef();
    render() {
      return (<CloseablePopup ref={popupRef} name="Closable Popup" />);
    }
  }
like image 118
Orar Avatar answered Sep 19 '22 20:09

Orar