惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

A
About on SuperTechFans
量子位
Apple Machine Learning Research
Apple Machine Learning Research
博客园 - 聂微东
V
Visual Studio Blog
小众软件
小众软件
Hugging Face - Blog
Hugging Face - Blog
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
博客园 - 司徒正美
V
V2EX
The GitHub Blog
The GitHub Blog
博客园_首页
月光博客
月光博客
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
MyScale Blog
MyScale Blog
博客园 - 叶小钗
F
Fortinet All Blogs
T
Tailwind CSS Blog
GbyAI
GbyAI
酷 壳 – CoolShell
酷 壳 – CoolShell
IT之家
IT之家
WordPress大学
WordPress大学
B
Blog
H
Help Net Security

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant
I Built a Job Tracker and These Bugs Nearly Finished Me —...
Solomon Isu · 2026-05-04 · via DEV Community

Hey Dev.to community 👋

I'm a growing developer and I just finished building my first
real full-stack project — a Job Application Tracker built with
Next.js, TypeScript, MongoDB and DnD Kit.

I'm writing this partly to document what I faced, partly to
laugh about it, and mostly to ask for advice from more experienced
developers on how to handle these situations better next time.


The Project

A Kanban-style job application tracker where you can:

  • Add, edit and delete job applications
  • Drag and drop between columns
  • Move jobs via dropdown menu
  • All updates reflect immediately without page refresh

Tech stack:

  • Next.js 16 (App Router)
  • TypeScript
  • MongoDB + Mongoose
  • Better Auth
  • DnD Kit
  • shadcn/ui + Tailwind CSS

The Bugs — A Sarcastic Love Letter 💌

1. The useEffect setState Anti-Pattern

I was calling setBoard and setColumns directly inside a useEffect.
React responded with a wall of red text about cascading re-renders.
Delightful.

The fix was simple — useState already handles initial values.
The useEffect was doing the same job twice.

👉 Advice needed: Is there a pattern you follow to know when
useEffect is actually necessary vs unnecessary?


2. TypeScript's Obsession With Types

initialBoard had 3 possible values (Board | null | undefined).
setBoard only accepted 2 (Board | null). TypeScript lost its mind.
I lost my mind. Eventually we came to an agreement.

The fix was using initialBoard?.columns in the if check which
gave TypeScript enough confidence to calm down.

👉 Advice needed: How do you handle these type narrowing situations
more elegantly in large codebases?


3. The UI That Refused To Update

Server actions were saving to the database perfectly. The UI
sat there staring at me like nothing happened.

Turns out telling the database something changed and telling
the UI something changed are two completely different conversations.
I had to build a full callback chain from useBoard all the way
down to each component.

👉 Advice needed: Is this callback chain pattern the right
approach or is there a cleaner way? Should I be using something
like Zustand or React Query instead?


4. revalidatePath — The Silent Callback Killer

Just when the callback chain was working — revalidatePath was
quietly running in the background wiping all callbacks out on
every action. onJobAdded is not a function it said.

Removing revalidatePath fixed it — but now I'm handling all
UI updates manually.

👉 Advice needed: What's the best practice here? revalidatePath
vs manual state updates? Or a combination of both?


5. "use cache" — The Freshness Illusion

Next.js was serving beautifully cached stale data on every refresh.
Move a job to a new column. Refresh. Gone. Back where it started.
Like it never happened.

Removing "use cache" fixed it immediately.

👉 Advice needed: How do you properly handle caching in Next.js
App Router without breaking real-time updates?


6. The DnD Hydration Mismatch

The crown jewel. DnD Kit generating DndDescribedBy-0 on the server
and DndDescribedBy-1 on the client. A difference of exactly ONE
number causing a wall of red hydration warnings on every single
page load.

Although purely cosmetic — it's a bloody pain in the ass.

The fix was the isMounted pattern — only rendering DndContext
on the client:

const [isMounted, setIsMounted] = useState(false);

useEffect(() => {
setIsMounted(true);
}, []);

if (!isMounted) return null;

👉 Advice needed: Is there a better way to handle DnD Kit
hydration issues in Next.js? Is this a known issue with a
planned fix?


What I Learned

Building a real project teaches you things no tutorial ever will.

  • React is opinionated. Respect it.
  • TypeScript is unforgiving. Respect it more.
  • Next.js caching will humble you.
  • Purely cosmetic bugs are still a bloody pain in the ass.
  • Debugging at 2am builds character apparently.

My Ask

I'm a growing developer and I'd love honest feedback from the
community:

  1. Are there better patterns for any of these solutions?
  2. What tools or libraries would have made this easier?
  3. What would YOU have done differently?

All advice welcome — roast me if you must. I can take it. 😂

GitHub: https://github.com/solodevx/venarium-job-application-tracker

Thanks for reading! 🚀