This is a Livecoding Recap – an almost-weekly post about interesting things discovered while livecoding ?. Always under 500 words and with pictures. You can follow my channel here. New streams almost every Sunday at 2pm PDT. There’s live chat, come say hai ?
Yesterday was supposed to be all about cutting up a large-ish codebase into small chunks that are easier to explain step-by-step. I was a great plan, but it didn't quite happen.
Instead of doing that, I went down the rabbit hole of optimizing the choropleth map from Livecoding 24. Turns out my H1B visualization wasn't slow because the dataset was big. It was slow because the map re-renders 3,220 county polygons on every update. ?
Let me explain.
We started with this:
See how it takes 2 or 3 seconds to react when you click a button? That's bad.
And we finished with this:
Takes just a second. Still slow, but a lot better. The dataset to crunch is big after all. ?
Unfortunately, the paint flashing isn't useful to show you what's fixed. Looks like a parent component repaints and flashes everything. This is unfortunate and a potential clue for further improvements.
To make this 50% to 66% speed improvement, we did two things:
- Added
shouldComponentUpdate
to theCounty
component - Avoided doing
_.find
to find data on every polygon draw
I don't know which improvement had a bigger effect, but when you _.find
in a N=290 array 3220 times, that's 933,800 function calls that you're making. Oops.
We fixed that by building a map beforehand. Like this:
const countyValueMap = _.fromPairs(
this.props.values.map((d) => [d.countyID, d.value])
);
Then rendering County
components in a loop, like this:
{counties.map((feature) => (
))}
That value
prop used to be _.find(counties, {countyID: feature.id})
and that was dumb.
Lesson learned. Big-O matters even when you're just doing JavaScript.
Inside County
, we added shouldComponentUpdate
. I don't know why React wasn't able to optimize this for us, but it wasn't. Maybe because we were passing props in as functions? Probably.
The new County
component looks like this:
class County extends Component {
shouldComponentUpdate(nextProps, nextState) {
const { zoom, value } = this.props;
return zoom !== nextProps.zoom || value !== nextProps.value;
}
render() {
// body from previous functional stateless version
}
}
We know for a fact that a county polygon only has to re-render when the map's zoom level changes or the value we're displaying changes. That enables the map to change size and the value to change polygon colors.
Excellent. Many lessons learned.
You can see the code for React + D3 choropleth maps on Github. It's embedded in a larger project, so there's some context-specific stuff, but the component itself is made to be pretty general.
Continue reading about Livecoding #29: Optimizing React choropleth map rendering
Semantically similar articles hand-picked by GPT-4
- Livecoding #24: A choropleth in React.js
- Livecoding #34: A Map of Global Migrations, Part 3
- Livecoding #12: towards animating 10k+ elements with React
- Livecoding #32: A Map of Global Migrations, Part 1
- Livecoding #33: A Map of Global Migrations, Part 2
Learned something new?
Read more Software Engineering Lessons from Production
I write articles with real insight into the career and skills of a modern software engineer. "Raw and honest from the heart!" as one reader described them. Fueled by lessons learned over 20 years of building production code for side-projects, small businesses, and hyper growth startups. Both successful and not.
Subscribe below 👇
Software Engineering Lessons from Production
Join Swizec's Newsletter and get insightful emails 💌 on mindsets, tactics, and technical skills for your career. Real lessons from building production software. No bullshit.
"Man, love your simple writing! Yours is the only newsletter I open and only blog that I give a fuck to read & scroll till the end. And wow always take away lessons with me. Inspiring! And very relatable. 👌"
Have a burning question that you think I can answer? Hit me up on twitter and I'll do my best.
Who am I and who do I help? I'm Swizec Teller and I turn coders into engineers with "Raw and honest from the heart!" writing. No bullshit. Real insights into the career and skills of a modern software engineer.
Want to become a true senior engineer? Take ownership, have autonomy, and be a force multiplier on your team. The Senior Engineer Mindset ebook can help 👉 swizec.com/senior-mindset. These are the shifts in mindset that unlocked my career.
Curious about Serverless and the modern backend? Check out Serverless Handbook, for frontend engineers 👉 ServerlessHandbook.dev
Want to Stop copy pasting D3 examples and create data visualizations of your own? Learn how to build scalable dataviz React components your whole team can understand with React for Data Visualization
Want to get my best emails on JavaScript, React, Serverless, Fullstack Web, or Indie Hacking? Check out swizec.com/collections
Did someone amazing share this letter with you? Wonderful! You can sign up for my weekly letters for software engineers on their path to greatness, here: swizec.com/blog
Want to brush up on your modern JavaScript syntax? Check out my interactive cheatsheet: es6cheatsheet.com
By the way, just in case no one has told you it yet today: I love and appreciate you for who you are ❤️