DEV Community

Rafael Leitão
Rafael Leitão

Posted on • Updated on

Using refs in React functional components (part 3) - instance-like variable

Hello everyone! 👋

For this last part of the series I will show another use of useRef which is not so common but can be handy at times.

One such case could be when you want to keep track of whether a component is mounted when using hooks.. However, as when using refs in general, updating a ref is a side effect so it should be done only inside a useEffect (or useLayoutEffect) or inside an event handler.

So, keep in mind that this post only demonstrates another use of the useRef() hook but you should reason if it would be the best approach to solve your problem. Hopefully, it will be another alternative for us to have in our toolbox :)

If you want to check, I also put the code for these examples on github.

Okay okay, let's see this case :)

1. Creating mutable instance-like variables

As the docs states, the ref object is a generic container whose current property is mutable and can hold any value, similar to an instance property on a class.

How is it similar?
In a class component, we can define instance variables in it and when there is a re-render the render method is executed again.

However, a functional component does not have a render function, the component itself, with everything defined in it being the render function which returns a JSX in the end. Thus, when there is a re-render the whole code in the functional component is executed again and if we have variables inside it will be initialized again with the default value.

Consider this example below. When we click on a button, this increments a counter set with useRef and with a local variable in the functional component:

import React, { useState, useRef } from 'react';

const SimpleValueRef = () => {
    const [show, setShow] = useState(false);
    let count = 0;
    let refCount = useRef(0);

    const increment = () => {
        refCount.current++;
        count++;
        console.log('The count: ', count);
        console.log('The refCount: ', refCount);
    };

    const showCounter = () => setShow(true);

    console.log(`Rendering SimpleValueRef with ref ${refCount.current}, without ref ${count}`)
    return (
        <div>
            <button onClick={increment}>Click to increment!</button>
            <button onClick={showCounter}>Show counter</button>
            {show && <p>Times you clicked on button: with ref {refCount.current}, without ref {count}</p>}
        </div>
    )
};
Enter fullscreen mode Exit fullscreen mode

Alt Text

As you can see in the console logs, every time we click on the first button both the count variable and refCount current property are updated and since there is no re-render both have the same value. When we click on the second button, we make a state change with the setShow function and this makes the functional component to re-render. All the code inside is executed again setting count variable to its initial value, 0, but the current property of refCount keeps the value as before.

From the docs:

This works because useRef() creates a plain JavaScript object. The only difference between useRef() and creating a {current: ...} object yourself is that useRef will give you the same ref object on every render.

This way, we see that with useRef we could have a property similar to an instance variable in a class but with a functional component thanks to the ref staying around over the lifetime of the component.

However, keep in mind that this was an example just to illustrate this use of refs in React. We could simply use a state to keep the counter updated and even though it would make the component re-render every time it would not be an issue in this case. There is also an easter egg with a problem related to React’s reconciliation technique( which hopefully I will make an article about to explain it with this example and to understand it more).

2. Conclusion

And that’s it! Hopefully this series was helpful to others always learning React just like me and that it made you understand a bit more about the uses of Refs in functional components.

If you have any questions or want to complement with something, feel free to comment below. Since these are my first posts, I’m looking forward to any feedback as well :)

3. References

This series would not be possible without other articles from awesome developers out there. If you want check what helped my learning, click on the links below:

https://medium.com/trabe/react-useref-hook-b6c9d39e2022
https://www.codementor.io/@dhananjaykumar/useref-hook-as-mutable-ref-object-ykb77fwvk
https://reactjs.org/docs/hooks-faq.html#is-there-something-like-instance-variables
https://www.robinwieruch.de/react-ref
http://naomiajacobs.com/useRef-vs-useState/

Top comments (0)