1

I had a react issue in which I was trying to fetch some data using an asynchronous function that might return sooner or later, called in response to the user's keystrokes (basically a typeahead function). Since older queries might return before newer ones, I wanted to keep track of the most recently submitted query string and only update the results if this most recent query string matched the query string that had been used to call the function.

I found two ways of doing this that worked equally well, from my vantage point. The first one seemed pretty good to me:

let currentSearchInput = '';

function TypeaheadList({searchInput}) {
    const [results, setResults] = React.useState([]);

    React.useEffect(() => {
        currentSearchInput = searchInput;

        getResults().then((results) => {
            if (currentSearchInput !== searchInput) return;
            setResults(results);
        }
    }
    ...
}

export default TypeaheadList;        

Then, I began to worry that I hadn't really ever seen this pattern before, and also remembered that react had useRef for situations like this, so I refactored like so:

function TypeaheadList({searchInput}) {
    const [results, setResults] = React.useState([]);
    const currentSearchInput = React.useRef();

    React.useEffect(() => {
        currentSearchInput.current = searchInput;

        getResults().then((results) => {
            if (currentSearchInput.current !== searchInput) return;
            setResults(results);
        }
    }
    ...
}

export default TypeaheadList;        

My questions are the following:

  1. Is the first code snippet an antipattern?
  2. If so, why? If not, why does react provide useRef at all?
eLillie
  • 653
  • 9
  • 17

1 Answers1

1

React.useRef will be unique to each instance of component while module-level variable will be shared across all instances of your component.

Think of module level variable as common store reference used by multiple instances of the component. If one instance updates the variable, when the other instance tries to reference it, it'll be the updated instance. This will not be the case with useRef.

For example,

let commonVariable;

function TypeaheadList(){
    const useRefVariable = React.useRef();
}

// In your app, let's say you're using this component at two places

// has it's own `useRefVariable` but refers to same commonVariable
<TypeaheadList />

// similar for this component - has it's own `useRefVariable` but refers to same commonVariable
<TypeaheadList />

// Here update to `useRefVariable` in one component will not affect the value in the other component.


We can't call one right and other anti-pattern. Both are different and it depends on your use case

vatz88
  • 2,422
  • 2
  • 14
  • 25