Exposing Selected Node Methods

In this example, the value we'll get from the ref will only contain the function blur(). The function itself is also "customized" to behave differently than what you'd normally expect.
RESETRUNFULL
<!DOCTYPE html><html><head>
<script src="https://unpkg.com/react@18/umd/react.development.js" crossorigin></script>
<script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js" crossorigin></script>
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
</head><body>
<div></div>
<script type="text/babel">
const MyInput = React.forwardRef((props, ref) => {
  const [val, setVal] = React.useState('');
  const inputRef = React.useRef();
  React.useImperativeHandle(ref, () => ({
    blur: () => {
      console.log("blurred");
      inputRef.current.blur();
    }
  }));
  return (<input {...props}
    ref={inputRef}
    value={val}
    onChange={e => setVal(e.target.value)} />);
});
const App = () => {
  const ref = React.useRef(null);
  const onBlur = () => {
    console.log(ref.current); // Only contains one property!
    ref.current.blur();
  };
  return <MyInput ref={ref} onBlur={onBlur} />;
};
const root = ReactDOM.createRoot(document.querySelector("div"));
root.render(<App />);
</script>
</body></html>

Since React 19, a function component can also receive ref as a plain prop, without wrapping it in forwardRef() — useImperativeHandle() works exactly the same way either way, since all it needs is the ref itself as its first argument. forwardRef() still works in React 19 (it's only deprecated, with a codemod available to remove it, not removed), but here is the same example written the React 19 way. Since ref-as-a-prop has no React 18 equivalent, this one demo loads React 19 via ES modules instead of the usual React 18 CDN build used elsewhere on this site:

The React 19 way: 'ref' is destructured out of props directly, no forwardRef() needed.
RESETRUNFULL
<!DOCTYPE html><html><head>
<script type="importmap">
{"imports": {"react": "https://esm.sh/react@19", "react-dom/client": "https://esm.sh/react-dom@19/client"}}
</script>
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
</head><body>
<div id="root"></div>
<script type="text/babel" data-type="module" data-presets="react">
import React, { useState, useRef, useImperativeHandle } from 'react';
import { createRoot } from 'react-dom/client';

function MyInput({ ref, ...props }) {
  const [val, setVal] = useState('');
  const inputRef = useRef();
  useImperativeHandle(ref, () => ({
    blur: () => {
      console.log("blurred");
      inputRef.current.blur();
    }
  }));
  return (<input {...props}
    ref={inputRef}
    value={val}
    onChange={e => setVal(e.target.value)} />);
}
function App() {
  const ref = useRef(null);
  const onBlur = () => {
    console.log(ref.current); // Only contains one property!
    ref.current.blur();
  };
  return <MyInput ref={ref} onBlur={onBlur} />;
}
createRoot(document.getElementById('root')).render(<App />);
</script>
</body></html>