This content originally appeared on DEV Community and was authored by Nick Taylor
In React, state manages data that can trigger re-renders. But what if you need a way to directly access document object model (DOM) elements or persist values that shouldn’t cause re-renders? That’s where the useRef hook comes in.
Typically, you’d do something like this.
import { useEffect, useRef } from "react";
export const SomeComponent = () => {
const firstInputRef = useRef<HTMLInputElement>(null);
useEffect(() => {
firstInputRef.current?.focus();
}, [firstInputRef.current]);
return (
<form>
<label>
Name:
<input type="text" ref={firstInputRef}/>
</label>
</form>
);
}
- We create a
useRef
namedfirstInputRef
and initialize it with null (as it won’t point to an element yet). - The
useEffect
hook runs after the component renders. - Inside
useEffect
, we check iffirstInputRef.current
exists (it will be the actual DOM element after the initial render). If it does, we callfocus()
to set focus on the input. - The dependency array
[firstInputRef.current]
ensuresuseEffect
only runs once when the reference changes (i.e., after the initial render).
In the above example, the useRef
hook creates a reference object that holds a mutable value, the HTML element, but this value can be anything, from a DOM element to a plain object. Unlike state, changes to a useRef
won’t trigger a re-render of your component.
Recently, I was working on Open Sauced’s StarSearch, a Copilot for git history feature we released at the end of May 2024.


We Made a Copilot Tool for you to Unlock the Power of Git History
BekahHW for OpenSauced ・ May 2
The ask was to be able to start a new StarSearch conversation. To do so, I had to stop the current conversation. If you’ve worked with OpenAI or similar APIs, they typically stream a ReadableStream as a response.
I initially had this feature working, but ran into issues if the response started to stream. The solution, create a reference to the readable stream via the useRef
hook and when a new conversation is started, cancel the one in progress. You can see these changes in the pull request (PR) below
fix: now a new StarSearch chat can be started if one was in progress
#3637
Description
Now isRunning
is reset to false
when starting a new conversation. This was preventing the stream conversation from beginning when a previous one was cancelled and a new conversation started.
Related Tickets & Documents
Fixes #3636
Mobile & Desktop Screenshots/Recordings
Before
After
Steps to QA
- Go to any workspace and open StarSearch
- Start a conversation
- Cancel it by clicking the back button or new conversation buttons in the compact StarSearch header.
- Start the new conversation.
- Notice the new conversation streams in.
Tier (staff will fill in)
- [ ] Tier 1
- [ ] Tier 2
- [ ] Tier 3
- [x] Tier 4
[optional] What gif best describes this PR or how it makes you feel?
So now, if someone presses the create a new conversation button, I cancel the current streaming response from StarSearch, e.g.
const streamRef = useRef<ReadableStreamDefaultReader<string>>();
...
const onNewChat = () => {
streamRef.current?.cancel();
...
};
...
- We create a
useRef
namedstreamRef
to hold the ReadableStreamDefaultReader. - The
onNewChat
function checks ifstreamRef.current
exists (meaning a stream is ongoing). - If a stream exists, we call
cancel()
onstreamRef.current
to stop it before starting a new conversation.
useRef
was the perfect solution for my use case. Maybe you’ll find the useRef
hook useful for something other than referencing an HTML element.
Stay saucy peeps!
If you would like to know more about my work in open source, follow me on OpenSauced.
This content originally appeared on DEV Community and was authored by Nick Taylor