あるのは知ってましたがたぶん初めて使いました
ref props というと いつも useRef で取得したオブジェクトを渡していました
それだけで困らなかったですし そもそも ref を渡すこと自体ほとんどなかったですし
ですがコールバック ref を使う機会がありました
React 標準以外の方法でイベントリスナをつけたい場合に使えます

例えばこのコードでは state に保存しているカウントが偶数のときのみ h1 を表示します
ref はこの h1 を参照させます
イベントリスナはクリックにつけているので h1 をクリックするごとに console にメッセージが表示されます

const App = () => {
const [count, setCount] = useState(0)
const ref = useRef()

useEffect(() => {
console.log("effect")
const handler = () => console.log("clicked")
ref.current?.addEventListener("click", handler, true)
return () => ref.current?.removeEventListener("click", handler, true)
}, [ref.current])

return (
<div>
<button onClick={() => setCount(count + 1)}>{count}</button>
{(count % 2 === 0) && (
<h1 ref={ref}>click me</h1>
)}
</div>
)
}

useEffect の依存配列で ref に設定された要素の変更を監視して変更があったら再設定してます
これをしないで依存配列を空にしてると h1 が一旦消えて再表示されたときに h1 要素が別物なのでクリックしても反応しなくなります

コールバック ref だと要素が変更されたときに要素を引数に受け取って関数を実行できます

const App2 = () => {
const [count, setCount] = useState(0)
const ref = useRef()

const refCallback = (elem) => {
const prev = ref.current
ref.current = elem

const handler = () => console.log("clicked")
prev?.removeEventListener("click", handler, true)
elem?.addEventListener("click", handler, true)
}

return (
<div>
<button onClick={() => setCount(count + 1)}>{count}</button>
{(count % 2 === 0) && (
<h1 ref={refCallback}>click me</h1>
)}
</div>
)
}

新しい要素にリスナをつけるだけなら useRef は不要ですが 前の要素を保持してリスナを削除するようにしてます
React はレンダリングも副作用も 2 回呼び出されるかもみたいなのが多いですし念のため

今回の例だと意味ないですが リスナを capture フェーズに付けてます
一部の bubbles が false なイベントを親で受け取ったり ライブラリなどが stopPropagation する場合でも受け取りたいとかで結構使うシーンはあるのにこういうことしないとリスナ設定できないのは不便ですね