DevNotes
@devnotes ·
React Part 6: Lists, keys and conditions
Most screens are lists of something, whether it's messages or search results.
From an array to a list
Remember map from JavaScript Part 6? In React, it turns data into elements:
map returns an array of <li> elements, and React draws each of them in place.
Keys
Every item in a list needs a key prop: a value that identifies that item, and stays the same for it, every time.
React uses keys to match items up between one draw and the next. When an item is added, removed or moved, the keys tell React which item is which, so it updates only what changed, and keeps each item's state, like text typed into a box inside it, with the right item.
Good keys come from your data: an id from the database, a username, a product code. They need to be:
- Unique among the items in that list.
- Stable: the same item keeps the same key forever.
You'll be tempted to use the index from map((item, index) => ...). That's only safe if items are only ever added at the end, and never removed, reordered or filtered. Otherwise React mixes items up, and you get bugs like the wrong row staying ticked after a delete. And never make keys with Math.random() while drawing: every draw then gets new keys, so React throws everything away and starts over each time.
Forget the key and React warns you in the console. Don't ignore that warning.
Showing things only sometimes
Three patterns cover nearly everything. && shows something, or nothing:
A ternary picks one thing or the other:
An early return swaps in a different screen entirely:
One trap with &&: if the left side is the number 0, React puts a "0" on the screen. {messages.length && <MessageList />} shows a stray 0 when there are no messages. Write {messages.length > 0 && <MessageList />} instead, so the left side is a real true or false.
Work out the data before drawing
Do the filtering and sorting above the return:
Notice matches isn't kept in state. It's worked out from the props every time the component draws. If a value can be calculated from what you already have, calculate it. Storing it as separate state means keeping two things in sync, and sooner or later they drift apart.
Try it
Show a list of five books with a search box above it that filters them by title as you type, and a "No books found" message when nothing matches. Use each book's id as its key.
Next: React Part 7: Load data with useEffect
Join WIK to like and reply to DevNotes and see more like this.