useMemo() vs. useState() — how I figured out the difference and usage

Daniel Babinszky
Towards Dev
Published in
3 min readJun 12, 2022

--

Custom hooks, particularly for state management, are essential in React. Every component that displays and updates data has its own state with a setter function and an actual phase. When I first started using React, I only knew about the useState() and useEffect() hooks, and yet now I use them almost every day.

At BitRaptors, we pay close attention to the smallest of details. We follow Clean Code principles and naming conventions, so basically we write code that can be handed over to another development team at any time for them to continue working on. And yeah. We absolutely hate terminal warnings.

For our latest project, we used Next.js instead of React, and I became attentive to an interesting warning to get rid of. When I simply wanted to save a value into a variable for the UI, the application dropped the following warning:

The ... object makes the dependencies of useEffect Hook
change on every render. To fix this, wrap the initialization
of ... in its own useMemo() Hook.

I got really curious about this useMemo(), especially because after reading the warning, it was really clear that I should use something that has dependencies to refresh if necessary.

I’ve figured out this:

You declare the state with an initial value to using useState() with useEffect():

const [state, setState] = useState(null)

then, when some other states will change, you can use useEffect() hook with dependencies to update the state:

useEffect(() => {
setState(state + 1)
}, [dependencies])

easy peasy.

A more realistic scenario is when you need to display and update data from an API on the user interface. You must retrieve the data, save it to a state, and implement an update function

const [data, setData] = useState(null)
const [title, setTitle] = useState(‘’)
useEffect(() => {
const _data = fetch…
setData(_data)
setTitle(_data.title)
}, [])
// an empty dependency array means it will run once when the component is mounted
const update = () => {
const newData = Object.assign(data, { title })
setData(newData)
// …and save to database
}
return(
<div>
<h1>{title}</h1>
<form>
<input onChange={(e) => setTitle(e.target.value)} type=’text’ name=’title’>
<button onClick={() => update()}>Update title!</button>
</form>
</div>
)

But what if we just want to display data rather than show and update it? The setState function will then be useless; it will only be called on the first render to set the state, and that will be it, no more updates.

This is where the useMemo() hook comes into play. It’s similar to a state, but without the setter function, and it’s more useful when you just want to display data on the UI, but you want it to be reactive (thanks to the useEffect() dependency array).

So, let’s say we only want to show information from the API and we want to use the useMemo() hook for that

// fetching data...const title = useMemo(() => {
return data.title
}, [data])

and that’s all there is to it. You write less, and cleaner code, but you still have a reactive variable, so when the value of data changes, the value of title changes as well.

In conclusion, the main difference here between useState() and useMemo() is determined by the need to update the data.

👋 I hope you found this article useful in your search for new material to learn from. Thank you for taking the time to read this!

☕️ You can support me by buying me a coffee: https://www.buymeacoffee.com/daanworks

📯 Subscribe to my e-mail list, and follow me here or on Twitter if you want to read more stories like this in the future!

--

--