Blog
Posts on software development, careers, and craft.
Problem: aria-labels are often implemented poorly
Problem: aria-labels are often implemented poorly. Here are 4 aria-label mistakes in one snippet: This reads as "User 1 expand button". 👎 Issues:...
React has over a dozen popular third-party state libraries
React has over a dozen popular third-party state libraries. React Query, Zustand, Redux, Jotai, Mobx, etc. Prediction: Third-party React state libr...
Habit: If a function accepts two arguments of the same type, I accept an object
Habit: If a function accepts two arguments of the same type, I accept an object. This protects from accidentally passing args in the wrong order.
The longer I work in software the more enjoyable my work is
The longer I work in software the more enjoyable my work is. My skills have improved. My autonomy has grown. My tools have gotten WAY better. As a...
I'm recommend using JSDoc comments above each property
I'm recommend using JSDoc comments above each property. Benefits: 1. It provides enhanced autocomplete support. The comments are exposed via modern...
Seriously, I think @kentcdodds deserves the developer equivalent of the...
Seriously, I think @kentcdodds deserves the developer equivalent of the Nobel prize for creating @TestingLib. A huge leap forward for testing maint...
Sometimes, we all have to cut corners
Sometimes, we all have to cut corners. But for some developers, it's their default mode. So, every PR is a landmine: ⚠️ basic typos loose types obv...
I'm hesitant to click approve on a PR that feels highly complex
I'm hesitant to click approve on a PR that feels highly complex. Here's 2 reasons why: 1. If it feels highly complex, a simpler approach may exist....
"I'll add tests in a separate PR"
"I'll add tests in a separate PR". Ouch. 5 reasons to add tests before merge: 1. Clear memory: Before merge, everything is fresh in my mind. I know...
I often see filter calls that needlessly fall back to an empty array
I often see filter calls that needlessly fall back to an empty array. It's unnecessary. JavaScript's array.filter always returns an array. Even whe...
Not trying to put Ryan on blast (I like Ryan, and Remix and React Router are...
Not trying to put Ryan on blast (I like Ryan, and Remix and React Router are wonderful), but: Disabled buttons are NOT accessible. Being able to "s...
⚠️ A tooltip on a disabled button isn’t accessible
⚠️ A tooltip on a disabled button isn’t accessible. It can’t be accessed via a screen reader. It can’t be triggered by a keyboard user. And often t...
Problem: Disabled fields and buttons aren’t accessible or discoverable
Problem: Disabled fields and buttons aren’t accessible or discoverable. Here a 4 ways to avoid using "disabled". Scenario 1: The form is loading, a...
Developers are liars
Developers are liars. We say “this can be null” when it’s actually required. We say “this property is optional” when it’s actually required. We say...
TypeScript rule: If a function requires something, the function's type...
TypeScript rule: If a function requires something, the function's type signature should require it. This sounds obvious and reasonable, but I often...
With TypeScript, I feel comfortable making big changes that would have...
With TypeScript, I feel comfortable making big changes that would have scared me in JavaScript. I can often make large scale, type-safe changes, an...
I'm getting tempted to use ESLint to warn on usage of useEffect
I'm getting tempted to use ESLint to warn on usage of useEffect. Something like: Please re-read "You Might Not Need useEffect" and then ask, do the...
I review a LOT of React code every day
I review a LOT of React code every day. Half my job is repeatedly saying two things: 1. "This state isn't necessary. The values can be derived from...
The risk with mocked tests: The test may not test anything
The risk with mocked tests: The test may not test anything. Example: I just reviewed a test that claimed to ensure a JSON API response was the expe...
General rule: The fewer mocks a test has, the more confidence the test provides
General rule: The fewer mocks a test has, the more confidence the test provides. A passing test with no mocks gives me the most confidence.
Top 10 React state libraries, sorted by downloads: 1
Top 10 React state libraries, sorted by downloads: 1. Redux (single store, typically with Redux Toolkit) 2. Apollo (for GraphQL - includes caching)...
Four interesting points about React Server Components: 1
Four interesting points about React Server Components: 1. All components are server-side rendered (SSR) by default, (even client components!) SSR r...
I'm really enjoying the Apple Studio monitor
I'm really enjoying the Apple Studio monitor. ✅ Excellent build quality. The clean metal build looks fantastic. ✅ Text is wonderfully crisp. ✅ It’s...
Some of my clients try to "hide" primary keys in the UI
Some of my clients try to "hide" primary keys in the UI. They consider using primary keys in the URL/links a security risk. But the primary keys ar...
When I see a type assertion like this in TypeScript: fish as Fish I read it...
When I see a type assertion like this in TypeScript: fish as Fish I read it as: fish dangerouslyAssumeThisIsA Fish Safe alternatives: 1. Create a u...
React mistake: Adding specific logic into a reusable component
React mistake: Adding specific logic into a reusable component. How to spot it: Are we adding props and logic to this component for a single, speci...
React-query problem: I fetched a list and I want to avoid needlessly...
React-query problem: I fetched a list and I want to avoid needlessly refetching the same data on my detail page. Solution: Use setQueryData to pre-...
Just ran no-type-assertion/no-type-assertion on a large TypeScript codebase
Just ran no-type-assertion/no-type-assertion on a large TypeScript codebase. It found 100's of things like this: 🚩 Needless, redundant type assert...
This is extremely useful, but most teams still aren’t doing it: Preview...
This is extremely useful, but most teams still aren’t doing it: Preview deployments - Automatically deploy each feature branch to a temporary envir...
A common case of needless state: Dialog visibility
A common case of needless state: Dialog visibility. Example: If a dialog displays when I click on a user, I only need one piece of state, not two....