In my recent books project I noticed a strange effect when playing with the filters - the smooth rainbow effect on the books sometimes worked well and sometimes was inconsistent. What was going on? It turns out this was a neat visual example of what React is doing when using the virutal dom to work out how to re-render components.
Each key should have a unique key prop
When using React you'll eventually come accross the error message 'Each key should have a unique "key" prop'. A bit of researching and you discover this is used by React to diff the virtual DOM and work out if it needs to re-render the component. That all makes sense but visually your app looks ok with the error message. Adding in a key gets rid of the error message and you assume that React is doing it's magic and everything is faster and smoother but you can't see any change. That's fine - lots of computer science isn't visual or visible - you need to look at other metrics to measure the real benefits. But sometimes it would be nice to see a visual example of what is actually happening.
Rainbow colors in my books project
Recently I built a project using React to list all the books I've read. While playing around with the filters I noticed that normally there was a smooth rainbow effect. Changing the filters removed some books and there were disonnects in the color of the remaining adjoining books. However, playing with the filters sometimes resulted in a smooth rainbow effect. Checkout the video to see this in action.
Choosing the right key
In the project I chose the key for each book to be the title (hopefully unique!). This seems a reasonable choice - if as the filters change that book is in the results then it doesn't need updating.
filteredBooks.map((book,i) =>
<Book
book={book}
key={book.title}
col={i}
/>)
The Book is a styled component. It takes in the color prop and creates a different background
background: hsla(${props => props.col}, 60%, 60%,1);
The result of this is a lovely, smooth, rainbow effect - the change in index rotates through the color circle
Style not linked to the key
The look of a book on the page is reliant on its index. However, if a book is shown in two consecutive filtered lists, React uses the title (which is the key) not the index to work out if it needs to re-render the component. So as we go from a list of all books to books only written by, say, female writers we go from a smooth rainbow effect to a more random look. The books by men are filtered out and the books by women retain their colour. If we now switch to a filter which is all men we go back to a smooth rainbow effect. All of the books needed to be re-rendered so we get a smooth rainbow again. Jumping between filters sometimes re-renders books so their colour reflects their index and sometimes their look carries over.
What's the right thing to do?
This is a fun side project and I quite like the inconsistency. But what if this was something more important? Maybe a list of purchase options where the look needed to be correct? By using styled components we have coupled some of our styles into how the component is rendered. To ensure we get the right look we should use some combination of index and title in the key - although this might end up resulting in slower render times as all items in the list would be re-rendered.
Another option is to solve the issues using vanilla CSS. Using SASS we can pump out a long list of nth-child selectors and create a rainbow effect that is completely decoupled from the rendering of the React components
What's right? Well depends on what you're building. Styled components are very popular at the moment but take note that as with any new technology they can introduce new areas you need to think about. For me, in this non essential side project, I'm just happy to have a fun, visual way to help me understand what is going on under the surface.