How to assign ref in forwardRef component
Tags: reactwebdevforwardre
Published: 2023-04-22 17:34:49

---
title: How to assign ref in forwardRef component
published: true
date: 2022-06-16 00:00:00 UTC
tags: reactwebdevforwardRe
canonical_url: https://bstefanski.com/assign-ref-forwardref-component
---

<section><h2 id="context">Context</h2>
<p>I had a component that I wanted to pass the <code>ref</code> prop into. To do that with React, you have to use <code>React.forwardRef</code> function and pass the second argument to the appropriate child component.<br>
<!-- -->It would look like this:</p>
<div>
<div></div>
<pre><div><span><span>
</span></span></div><div><span><span></span><span>export</span><span> </span><span>const</span><span> </span><span>YourComponent</span><span> </span><span>=</span><span> </span><span>React</span><span>.</span><span>forwardRef</span><span>&lt;</span><span>HTMLDivElement</span><span>,</span><span> </span><span>YourComponentProps</span><span>&gt;</span><span>(</span><span> </span></span></div><div><span><span> </span><span>function</span><span> </span><span>ComponentNameForDebugging</span><span>(</span><span> </span></span></div><div><span><span> </span><span>{</span><span> className</span><span>,</span><span> children </span><span>}</span><span>,</span><span> </span></span></div><div><span><span> ref</span><span> </span></span></div><div><span><span> </span><span>)</span><span> </span><span>{</span><span> </span></span></div><div><span><span> </span></span></div><div><span><span> </span><span>return</span><span> </span><span>(</span><span> </span></span></div><div><span><span> </span><span>&lt;</span><span>Wrapper</span><span> </span></span></div><div><span><span> </span><span>className</span><span>=</span><span>{</span><span>className</span><span>}</span><span> </span></span></div><div><span><span> </span><span>ref</span><span>=</span><span>{</span><span>ref</span><span>}</span><span> </span></span></div><div><span><span> </span><span>&gt;</span><span> </span></span></div><div><span><span> </span><span>{</span><span>children</span><span>}</span><span> </span></span></div><div><span><span> </span><span>&lt;/</span><span>Wrapper</span><span>&gt;</span><span> </span></span></div><div><span><span> </span><span>)</span><span>;</span><span> </span></span></div><div><span><span> </span><span>}</span><span> </span></span></div><div><span><span></span><span>)</span><span> </span></span></div><div><span><span>
</span></span></div></pre>
</div>
<p>And now, what if I wanted to access that <code>ref</code> inside the <code>YourComponent</code>. Normally I would try to access it through <code>ref.current</code>, but here it's different.<br>
<!-- -->The <code>ref</code> variable (forwardRef's second parameter) doesn't have .current property since it is a function. A function that takes <code>HTMLDivElement</code> as an argument.</p></section><section><h2 id="solution">Solution</h2>
<p>In such a case, what I need to do is:</p>
<ul>
<li>create a new ref inside <code>YourComponent</code>, let's call it <code>testRef</code>,</li>
<li>in <code>Wrapper</code> component, add lambda function as a value of <code>ref</code> prop. With HTMLDivElement as a parameter,</li>
<li>assign the value of a lambda's parameter to <code>testRef.current</code>
</li>
<li>call the <code>ref(el: HTMLDivElement | null)</code> and pass the lambda's parameter as an argument.</li>
</ul>
<p>This would look like this:</p>
<div>
<div></div>
<pre><div><span><span>
</span></span></div><div><span><span></span><span>export</span><span> </span><span>const</span><span> </span><span>YourComponent</span><span> </span><span>=</span><span> </span><span>React</span><span>.</span><span>forwardRef</span><span>&lt;</span><span>HTMLDivElement</span><span>,</span><span> </span><span>YourComponentProps</span><span>&gt;</span><span>(</span><span> </span></span></div><div><span><span> </span><span>function</span><span> </span><span>ComponentNameForDebugging</span><span>(</span><span>{</span><span> className</span><span>,</span><span> children </span><span>}</span><span>,</span><span> ref</span><span>)</span><span> </span><span>{</span><span> </span></span></div><div><span><span> </span><span>const</span><span> testRef </span><span>=</span><span> </span><span>useRef</span><span>&lt;</span><span>HTMLDivElement</span><span> </span><span>|</span><span> </span><span>null</span><span>&gt;</span><span>(</span><span>null</span><span>)</span><span>;</span><span> </span></span></div><div><span><span> </span></span></div><div><span><span> </span><span>return</span><span> </span><span>(</span><span> </span></span></div><div><span><span> </span><span>&lt;</span><span>Wrapper</span><span> </span></span></div><div><span><span> </span><span>className</span><span>=</span><span>{</span><span>className</span><span>}</span><span> </span></span></div><div><span><span> </span><span>ref</span><span>=</span><span>{</span><span>(</span><span>el</span><span>)</span><span> </span><span>=&gt;</span><span> </span><span>{</span><span> </span></span></div><div><span><span> testRef</span><span>.</span><span>current </span><span>=</span><span> el</span><span>;</span><span> </span></span></div><div><span><span> </span></span></div><div><span><span> </span><span>if</span><span> </span><span>(</span><span>typeof</span><span> ref </span><span>===</span><span> </span><span>'function'</span><span>)</span><span> </span><span>{</span><span> </span></span></div><div><span><span> </span><span>ref</span><span>(</span><span>el</span><span>)</span><span>;</span><span> </span></span></div><div><span><span> </span><span>}</span><span> </span></span></div><div><span><span> </span><span>}</span><span>}</span><span> </span></span></div><div><span><span> </span><span>&gt;</span><span> </span></span></div><div><span><span> </span><span>{</span><span>children</span><span>}</span><span> </span></span></div><div><span><span> </span><span>&lt;/</span><span>Wrapper</span><span>&gt;</span><span> </span></span></div><div><span><span> </span><span>)</span><span>;</span><span> </span></span></div><div><span><span> </span><span>}</span><span> </span></span></div><div><span><span></span><span>)</span><span>;</span><span> </span></span></div><div><span><span>
</span></span></div></pre>
</div>
<p>but it doesn't look the best! We could create a simple utility class for that or.... steal it from StackOverflow from the author you don't remember and can't find at the time of writing a blog post!</p>
<div>
<div></div>
<pre><div><span><span>
</span></span></div><div><span><span></span><span>import</span><span> </span><span>{</span><span> </span><span>MutableRefObject</span><span>,</span><span> </span><span>Ref</span><span> </span><span>}</span><span> </span><span>from</span><span> </span><span>'react'</span><span>;</span><span> </span></span></div><div><span><span> </span></span></div><div><span><span></span><span>export</span><span> </span><span>const</span><span> assignRefs </span><span>=</span><span> </span><span>&lt;</span><span>T</span><span> </span><span>extends</span><span> </span><span>unknown</span><span>&gt;</span><span>(</span><span>...</span><span>refs</span><span>:</span><span> Ref</span><span>&lt;</span><span>T </span><span>|</span><span> </span><span>null</span><span>&gt;</span><span>[</span><span>]</span><span>)</span><span> </span><span>=&gt;</span><span> </span><span>{</span><span> </span></span></div><div><span><span> </span><span>return</span><span> </span><span>(</span><span>node</span><span>:</span><span> T </span><span>|</span><span> </span><span>null</span><span>)</span><span> </span><span>=&gt;</span><span> </span><span>{</span><span> </span></span></div><div><span><span> refs</span><span>.</span><span>forEach</span><span>(</span><span>(</span><span>r</span><span>)</span><span> </span><span>=&gt;</span><span> </span><span>{</span><span> </span></span></div><div><span><span> </span><span>if</span><span> </span><span>(</span><span>typeof</span><span> r </span><span>===</span><span> </span><span>'function'</span><span>)</span><span> </span><span>{</span><span> </span></span></div><div><span><span> </span><span>r</span><span>(</span><span>node</span><span>)</span><span>;</span><span> </span></span></div><div><span><span> </span><span>}</span><span> </span><span>else</span><span> </span><span>if</span><span> </span><span>(</span><span>r</span><span>)</span><span> </span><span>{</span><span> </span></span></div><div><span><span> </span><span>(</span><span>r </span><span>as</span><span> </span><span>MutableRefObject</span><span>&lt;</span><span>T</span><span> </span><span>|</span><span> </span><span>null</span><span>&gt;</span><span>)</span><span>.</span><span>current </span><span>=</span><span> node</span><span>;</span><span> </span></span></div><div><span><span> </span><span>}</span><span> </span></span></div><div><span><span> </span><span>}</span><span>)</span><span>;</span><span> </span></span></div><div><span><span> </span><span>}</span><span>;</span><span> </span></span></div><div><span><span></span><span>}</span><span>;</span><span> </span></span></div><div><span><span>
</span></span></div></pre>
</div>
<p>and the final YourComponent's form is...</p>
<div>
<div></div>
<pre><div><span><span>
</span></span></div><div><span><span></span><span>export</span><span> </span><span>const</span><span> </span><span>YourComponent</span><span> </span><span>=</span><span> </span><span>React</span><span>.</span><span>forwardRef</span><span>&lt;</span><span>HTMLDivElement</span><span>,</span><span> </span><span>YourComponentProps</span><span>&gt;</span><span>(</span><span> </span></span></div><div><span><span> </span><span>function</span><span> </span><span>ComponentNameForDebugging</span><span>(</span><span>{</span><span> className</span><span>,</span><span> children </span><span>}</span><span>,</span><span> ref</span><span>)</span><span> </span><span>{</span><span> </span></span></div><div><span><span> </span><span>const</span><span> testRef </span><span>=</span><span> </span><span>useRef</span><span>&lt;</span><span>HTMLDivElement</span><span> </span><span>|</span><span> </span><span>null</span><span>&gt;</span><span>(</span><span>null</span><span>)</span><span>;</span><span> </span></span></div><div><span><span> </span></span></div><div><span><span> </span><span>return</span><span> </span><span>(</span><span> </span></span></div><div><span><span> </span><span>&lt;</span><span>Wrapper</span><span> </span><span>className</span><span>=</span><span>{</span><span>className</span><span>}</span><span> </span><span>ref</span><span>=</span><span>{</span><span>assignRefs</span><span>(</span><span>testRef</span><span>,</span><span> ref</span><span>)</span><span>}</span><span>&gt;</span><span> </span></span></div><div><span><span> </span><span>{</span><span>children</span><span>}</span><span> </span></span></div><div><span><span> </span><span>&lt;/</span><span>Wrapper</span><span>&gt;</span><span> </span></span></div><div><span><span> </span><span>)</span><span>;</span><span> </span></span></div><div><span><span> </span><span>}</span><span> </span></span></div><div><span><span></span><span>)</span><span>;</span><span> </span></span></div><div><span><span>
</span></span></div></pre>
</div></section><section><h2 id="solution-1">Solution</h2></section>