Updating multiple DOM nodes using React Hooks
Tags: react, hooks, uselayouteffect, gatsby
Published: 2020-05-24 22:51:52

(**Disclaimer**: I'm not a UX designer, or an IXD specialist, so this article is based on a fun experiment, and my specific use case)

TL;DR: You can use `useLayoutEffect()` to add styling to multiple components if you're crazy like me!

So far during lockdown (or isolation, quarantine, #stayathome, social distancing, whatever floats your boat) I have succeeded in the following:
 
* Making banana bread
* Gutting my room (goodbye shoes from 2007)
* Finding a new taste for gardening
* Spending far too much money buying (and preparing to customize) an Ergodox EZ (the excitement is real)
* And getting around to building my own website.

I am completely against the idea that everyone should use this time to improve their technical skills, or have five side projects they should be working on; as I very quickly realised, we are working during a crisis, not just working from home. *That* being said, I have genuinely wanted (and felt in the right headspace) to expand my knowledge, and as a full stack engineer specialising in front end development, I obviously gravitated towards a new framework, this time around being [GatsbyJS](https://www.gatsbyjs.org/). I have been keen to look at [Next.js](https://nextjs.org/), but for the purpose of a small portfolio website, I felt like Gatsby offered a quick (and fast) setup, with a less steep learning curve. Maybe for 2.0.

Like any portfolio website I wanted to incorporate navigation of some kind, but I had commissioned an illustration for my main landing page; adding a top nav felt quite...clunky. The incredible [Kai Kwong](https://www.instagram.com/_dollgirls) created the design, so I had the brainwave to grab one of the SVGs, add a spin to it, and boom, we have some cute, theme-compatible, `:hover` navigation.

![There's a gif because why not](https://media.giphy.com/media/Pm9kEyv0myPRiIPBwc/giphy.gif)<figcaption>Hurry up and get to the point, Beth</figcaption>

Cute right?

But what about mobile?

:woman_facepalming:

Although beautiful on a desktop, my new navigation just didn't have the same result on mobile, particularly with the addition of `:hover` behaviour. I reluctantly started working with a left nav, and then had **another** brainwave (my Saturday nights have been wild I am telling you): why not both? Why not have a left nav which triggered the star SVG animation when on desktop, and on mobile became the prime mode of navigation? Going against EVERYTHING I knew about UX, but I liked it, so screw it!

I had dabbled in React Hooks, but as the product I developed (professionally, the one I work on that makes me money) was still at v16.4, the opportunities to experiment with the various hooks was in my own personal time. The problem I now faced couldn't be resolved with CSS (I had an unordered list for a left nav, with the star SVG navigation being at different depths within the DOM), and I was initially leaning towards `useEffect()` (it is a side effect after all), but as I was manipulating the DOM my researching (ahem, Googling) lead me to `useLayoutEffect()`. As every blog post on the topic states:

> The signature is identical to useEffect, but it fires synchronously after all DOM mutations.

What this basically means is that unlike the asynchronous behaviour of `useEffect()`, `useLayoutEffect()` is blocking, and runs prior to browser painting. You generally don't want to use it due to it's blocking nature, but as I wanted the `:hover` interactions to be as smooth as possible, and as the function wouldn't be long running, performance hits would be minimal. To illustrate the difference in response time I've included two snippets of the design I was going with (albeit slightly tweaked), the first is using the `useEffect()` hook:

{% codepen https://codepen.io/eglenfield/pen/WNQWeOE %}

And the second uses the `useLayoutEffect()` hook:

{% codepen https://codepen.io/eglenfield/pen/jObJjYR %}

Although milliseconds in difference, to the human eye any slight delay is noticeable, as well as the more noticeable flicker when changing selection. As this is a CodePen I kept it to a one-way binding between the left nav and the individual divs, but in a React project you could have as many components linked in this way (I have no idea why but each to their own) as you like, and a two-way binding could be formed. 

Feel free to nab the code for your desire of strange and wonderful navigation patterns (like myself), I will likely be posting more as the website develops, so stay tuned! 

![That's all folks](https://media.giphy.com/media/mR3dXKpI6P8CA/giphy.gif)