Cory House

Cory House

@housecor.com

Courses: http://pluralsight.com YouTube: http://youtube.com/@housecor Consulting: http://reactjsconsulting.com ⚛️

2.2K followers61 following136 posts

How I handled React state over 10 years: 2014: Class state 2016: Redux 2018: useState, useReducer, useContext 2020: React query 2021: Zustand for globals 2024: useOptimistic, useTransition, useFormStatus, useActionState, RSC 2025: Tanstack DB or sync engine (Zero, Electric, Convex)

TypeScript syntax is often inspired by JavaScript. In some cases, TS even uses the exact same syntax as JS for a different purpose. The difference? JS features focus on values. TS features focus on types. Here's a few examples.

It’s live! “TypeScript: Deep Dive” explores advanced TS concepts: - Utility types - Generics - Mapped types - Conditional types - Template literal types - Runtime validation - Decorators - tsconfig techniques And over 250+ examples! Get 20% off at launch here: dometrain.com/course/deep-...

LLMs are handy when working with the command line. I wanted a count of all the exercise files in my new course. ChatGPT provided the correct Bash command immediately.

It’s done! I’ve been heads down for 3 months creating my most ambitious course yet: “TypeScript: Deep Dive” Just recorded the final clip. This course is 7 hours of advanced features, tips, patterns, and tricks to level up your TS skills. Publishing this week on Dometrain!

When migrating a codebase from JS to TS, there are two schools of thought: 1. Start strict, and loosen in spots as needed. 2. Start loose, and migrate to stricter rules over time. I prefer 1. It's safer. Default strict. Loosen when necessary.

With 2, we may never bother becoming stricter. And any new code is held to a low standard, which creates "type debt". With 1, new code is held to a strict standard, and existing code can selectively have looser typing rules via nested tsconfigs, or by disabling TS in spots if necessary.

Vibe coding is the modern version of copy/pasting code you don’t understand from Stack Overflow. It seems fine at first, but at some point you need to understand how to code.

Problem: Some interfaces like dates, times, localStorage, the URL, and the file system are “globals” that may change at any time. This makes it difficult to set up complex edge cases and hampers testing. Solution: Instead of coding against these APIs directly, wrap access in an interface.

Result: Now we can code and test against a mocked implementation in non-prod environments. The mocked implementation can be deterministic and fast, and thus allow quickly testing our business logic against many scenarios. In prod, the wrapper implementation merely forwards to the real APIs.

Problem: When I correct an LLM it “forgets” and makes the mistake again later. Solution: 1. Create a llm-learning file. 2. Tell the LLM to write to that file each time I correct it. (I use copilot-instruction.md to instruct Copilot) Now it “learns” over time!

I validate all my runtime inputs: -Cookies -Local storage -URL params -API responses -Form values -Environment variables I use Zod to validate runtime inputs. So, I don’t need to worry if the input is malformed. I show how I work with Zod in detail in TypeScript: Deep Dive”. Publishing in May!

Claim: "Those who can't do, teach". Reality: "To go deeper, teach." For example, I've worked successfully in TypeScript for years. But now that I'm writing a deep dive course, I'm finding edge cases that I hadn't naturally explored as a practitioner. Teaching forces me to grow.

I'm reviewing a TypeScript codebase that's filled with type assertions like this. return fieldErrors as { [key: string]: { errors: string[] } } Type assertions are NOT safe. It's saying "Trust me TypeScript, it's fine." Instead, validate. Consider Zod, ArkType, etc.

There are many JS runtimes - Node, Deno, Bun, etc. Just learned about a new one: Bare. Bare is unique: - Light (runs on mobile) - No server (great for P2P apps) - Not tied to a specific JS engine. - Separate modules (Upgrade modules when desired. Install what you need) More: bare.pears.com

“We don’t have time to write tests” isn’t a valid excuse anymore. I'm presenting "Creating Automated Tests with AI" April 23 at 11AM ET. In this webinar I'll show how to quickly generate tests using ChatGPT, Copilot, and Applitools Autonomous. Sign up: applitools.info/8y6

applitools.infoCreating Automated Tests with AI | April 23 • 11 AM ETLearn how to use GitHub Copilot, ChatGPT, and Applitools Autonomous to generate reliable automated tests—fast. In this session with Cory House, discover modern AI-driven workflows for Playwright, Vite...

I've heard people say "spelling mistakes in code are harmless". I disagree. Spelling mistakes slow reading, create confusion, and can lead to bugs. Solution: Run cspell as part of your CI process. Here's an example cspell just found - a misspelled style that wasn't applying.

PSA 📢: This isn’t error handling. .catch((e) => console.log(e)) It's error swallowing. The user isn’t watching the console. Solution: Show the user a friendly non-technical message like "Sorry, an error occurred. Please try again later."

Problem: Unused npm dependencies. They make package.json harder to read, bloat node_modules, waste our time updating packages we don’t use, and create confusion about what our project requires. Solution: npx depcheck It lists unused dependencies.

Problem: I want to see a list of the settings I've changed in VS Code. Solution: Search for @modified. This displays a list of modified settings. I used this today because I recently changed a setting that I wanted to revert, and couldn't recall the setting's name.

A React RSC payload includes 3 things: 1. The rendered server component. 2. Client component placeholders, with a reference to the JS chunk containing the client code. 3. Props passed from server components to client components. 3 is the place to watch for needless bloat.

Example of needless RSC payload bloat: Passing a large array of objects with many properties from a server component to a client component when only some of the properties are used by the client component. Solution: Only pass necessary data via props from server to client.

Now that Node, Bun, and Deno can run TS files directly without compilation, using JSDoc syntax to declare TypeScript types is even harder to justify. JSDoc syntax is more verbose, lacks full feature support, and is harder to read. Look at this comparison. Easy choice.

I think I finally have my phone-friendly vertical video format dialed in. I'm using an iPad with a Neewer teleprompter as my monitor so I can look directly at the code as I narrate. And Camtasia creates the slick captions. Thoughts?

I published my 16th course today (this time with a new publisher, Dometrain). Before every course I think "I know this topic well". Then I start writing, and realize I need to dig deeper. The act of teaching is powerful: - Exposes knowledge gaps - Explaining things fosters deeper understanding

Just submitted the final clips for "TypeScript: Getting Started". 🎉 The course explores primitive types, arrays, tuples, enums, interfaces, functions, classes, modules, using TS with and without a compiler, features to avoid, and much more. Publishing this week on Dometrain!

V0's system prompt specifies these naming and casing rules. I agree with all this. For years, I used PascalCase for React components. But I now I use kebab-case instead to avoid casing issues.

In my experience, it’s rare to find someone in QA who is as good at writing automated tests as a developer. My theory on why: If you’re good at writing automated tests, then you’re probably good enough to become a dev and make more money.

What I love about Tanstack start: Simplicity. Competitors have larger, more confusing APIs because they have to support previous “mistakes”. Tanstack pulled an Apple - they waited and watched the early movers, then executed supremely well. Result? It’s wonderfully elegant.

Situation: You have a separate QA team or SDET embedded with your team. When should QA / SDET test a new feature? 3 options: 1. Before merge, in an ephemeral environment, or by pairing with dev 2. After merge in QA/UAT/staging environment 3. In prod My take? Prefer 1. 1/2

Why 1? It shifts quality left. Or, consider 3, since prod testing is the only way to truly prove it works. Use feature flags to hide until QA approves. But avoid 2 - It leads to batching releases which inhibits continuous delivery.

Controversial opinion: 🌶️ I prefer for all quality checks to occur *before* merge. Here's why. Merging code that hasn't been fully quality checked leads to batching work. It means we need to maintain a long-lived environment (like QA, UAT, or Staging) to integration test all our changes... 1/3

It means need more release overhead - we need to agree on a release cadence, release cutoff dates, etc. This encourages devs to rush to hit release cutoff dates too. And it leads to devs getting pulled back into work days later if their code doesn't pass inspection in some other environment. 👎

In contrast, if all quality checks occur *before* merge, we can automatically deploy the code when it's merged. So all the release overhead above melts away. No more batching, coordination overhead, release planning, etc. Code deploys to prod when we merge, because we know it's good enough. 🔥