1

I have a set of Components that should not use react-popper internally. I'm trying to have them be used as Reference with react-popper. I get that the solution is to use forwardRef, however, I spent hours trying to do it without great success.

Is there any way someone could provide a sample for a simple case ? Here is a simple textbox Component that needs an internal ref : how should it be rewritten or wrapped to be used as a Reference ?

import React, { useEffect, useRef } from 'react';

const Textbox = ({
  autofocus,
  ...props
}) => {
  // handle auto-focus
  const node = useRef();
  useEffect(() => {
    if (autofocus) {
      // focus & select the whole text
      node.current.focus();
      node.current.setSelectionRange(0, 9999);
    }
  },
  // do it only once
  []);

  return (
    <input
      type="text"
      ref={node}
      {...props}
    />
  );
};
Mose
  • 1,781
  • 3
  • 16
  • 35

1 Answers1

1

Sure! To use this Textbox component as a reference with react-popper, you'll need to use React.forwardRef to create a new component that passes the ref to the underlying input element. Here's an example of how you can do it:

import React, { useEffect, useRef, forwardRef } from 'react';

const Textbox = forwardRef(({
  autofocus,
  ...props
}, ref) => {
  // handle auto-focus
  const node = useRef(null);
  useEffect(() => {
    if (autofocus) {
      // focus & select the whole text
      node.current.focus();
      node.current.setSelectionRange(0, 9999);
    }
  }, [autofocus]);

  return (
    <input
      type="text"
      ref={ref || node}
      {...props}
    />
  );
});

export default Textbox;

Here, we're using forwardRef to create a new component that accepts a ref as a prop, and passes it along to the underlying input element. We're also using useRef to create a local ref that we can use to access the input element if no ref prop is provided.

Note that we've added a default value of null to the useRef call, and we're passing [autofocus] to the useEffect hook to avoid a missing dependency warning.

With this setup, you should be able to use the Textbox component as a reference with react-popper like so:

import { usePopper } from 'react-popper';
import Textbox from './Textbox';

function MyComponent() {
  const [referenceElement, setReferenceElement] = useState(null);
  const [popperElement, setPopperElement] = useState(null);
  const { styles, attributes } = usePopper(referenceElement, popperElement);

  return (
    <>
      <Textbox ref={setReferenceElement} />
      <div ref={setPopperElement} style={styles.popper} {...attributes.popper}>
        ...
      </div>
    </>
  );
}

Here, we're passing the setReferenceElement function to the ref prop of the Textbox component, which allows us to access the input element later on with referenceElement. We're also passing the setPopperElement function to a div element that we want to position relative to the input element using react-popper. We're using the usePopper hook to calculate the positioning of the div, and we're applying the resulting styles and attributes to the div using spread syntax.

  • 1
    I succeeded in doing that years ago and I did as you described. Very good answer sir ! – Mose Apr 20 '23 at 14:30