0

I want to detect click outside of the React functional component.

Then I found the following article and implemented code accordingly.

Detect click outside React component

But my code does not work. I understand the cause, however don't know solution.

import React from 'react';
import Foo from 'foo'; // <- Functional component in the node_modules

export default class extends React.PureComponent {
  private readonly refRoot = React.createRef();
  public componentDidMount() {
    document.addEventListener('click', this.clickOutside);
  }
  public componentWillUnmount() {
    document.removeEventListener('click', this.clickOutside);
  }
  private clickOutside(ev: MouseEvent) {
    if (refRoot.current.contains(ev.target)) {
      console.log('clicked outside.');
    }
  }
  public render(){
    return (
      <Foo ref={this.refRoot}> // <- Doubt.
        ...
      </Foo>
    );
  }
}

Because cannot use the ref attribute on function component.

Maybe able to solve it by wrapping it with a div element, but I want to avoid complicating the stratum of the DOM any more when rendered to HTML.

What do you have any ideas?

  • If I understood the question correctly look into forwarding refs... https://reactjs.org/docs/forwarding-refs.html – SakoBu Jan 25 '19 at 06:53
  • You want to forward the ref to the Foo component - in this case use a different name for the prop. for Example, ``, then inside Foo attach the refParam to a dom element `
    `
    – Ben Carp Jun 18 '19 at 08:28

2 Answers2

0

If you want to use ref inside of functional component, then rather than passing it from parent, you can use React hooks API. https://reactjs.org/docs/hooks-reference.html#useref

Please check the above ^^

TJcobra
  • 49
  • 4
  • Awesome! Thank you for answer. I'm very interested in React Hooks so I tried upgrading from v16.7.0 to v16.8.0-alpha.1. But `useRef` was `undefined`. mmm:/ – kurone-kito Jan 28 '19 at 07:49
0

The idea to create a ref on the DOM element rendered inside of Foo which you can do by passing it as a props which can be used in Foo

  <Foo innerRef={this.refRoot}> 
    ...
  </Foo>

Inside Foo:

const Foo = (props) => {
   return <div ref={props.innerRef}>{/* data here */}</div>
}

or you could use React.forwardRef to forward Foos ref to its children

const Foo = React.forwardRef(props, ref) => {
   return <div ref={ref}>{/* data here */}</div>
}

Parent

public render(){
    return (
      <Foo ref={this.refRoot}> // <- Doubt.
        ...
      </Foo>
    );
  }
Shubham Khatri
  • 270,417
  • 55
  • 406
  • 400
  • Thank you for answer. The `Foo` component is in node_modules, and cannot be edited. Is unavoidable that adding a dummy `div` element and wrapping it, for getting `ref`? – kurone-kito Jan 28 '19 at 07:33
  • If Foo is in node_modules,then you can search in the library docs whether they allow a custom ref to the component using any prop. IF not than you need to add a div – Shubham Khatri Jan 28 '19 at 07:36
  • The component seem not allow custom `ref`. Hmm, I give up and wrapping by `div`. That seems easy to implement using `airbnb/react-outside-click-handler`. Thank you for thinking nice solutions. – kurone-kito Jan 28 '19 at 09:32