Skip to content
Submitted 8 days ago

kanban task app with Nextjs and dnd-kit

next, firebase, react, vite
LVL 3
Jia He530
@JiaHe35354
A solution to the Kanban task management web app challenge

Solution retrospective


What are you most proud of, and what would you do differently next time?

I am most proud of architecting a highly performant global state management system using the React Context API and useReducer. Managing a Kanban board requires complex, nested CRUD operations and high-frequency updates during drag-and-drop events.

To solve this, I implemented a normalized data structure (using tasksById and columnTaskIds). This allowed for O(1) task lookups and ensured that drag-and-drop reordering stayed buttery smooth by minimizing unnecessary re-renders. Successfully implementing Optimistic UI updates—where the state updates instantly while the database syncs in the background—gave the application a native, professional feel.

Next time, I would integrate a dedicated server-state management library like TanStack Query (React Query). While the Context API was excellent for learning the fundamentals of state orchestration, managing loading, error, and caching states manually for every Firestore call became quite verbose.

What challenges did you encounter, and how did you overcome them?

Handling High-Frequency State Updates in onDragOver

The Issue: During the implementation of cross-column dragging, I encountered the "Maximum update depth exceeded" error. This happened because onDragOver fires continuously as the mouse moves. Without a guard clause, the app was attempting to re-calculate task orders and update the global context dozens of times per second, even if the task hadn't actually moved to a new position or column.

The Solution: I implemented a multi-layered "guard" system within the handleDragOver function to ensure updates only occur when a meaningful change happens:

Spatial Guard (lastUpdateRef): I used a useRef to store a unique key composed of the activeId, overId, and the newIndex. Before dispatching a state update, I check if the current movement matches this key. If it does, I return early.

Column Validation: I added checks to ensure updates only fire if the task is actually hovering over a valid droppable container or a different column than its current one.

Optimistic Local Reordering: Instead of syncing with the database during the drag, I created reorderTasksLocal. This logic prioritizes immediate visual feedback by updating the local UI first. By deferring the heavy database communication until the task is dropped, I prevented the interface from stuttering or freezing during the move.

What specific areas of your project would you like help with?

I would specifically like feedback on my handleDragOver logic in Board.js.

While I implemented a useRef guard to prevent excessive state updates, I’m curious if there is a more efficient way to handle the cross-column sorting or if there are better collision detection strategies (currently using pointerWithin) to make the landing zones more predictable. I'd love to know if my approach to 'optimistic' local reordering follows best practices for a complex Kanban board.

Code
Loading...

Please log in to post a comment

Log in

Community feedback

No feedback yet. Be the first to give feedback on Jia He’s solution.

Join our Discord community

Join thousands of Frontend Mentor community members taking the challenges, sharing resources, helping each other, and chatting about all things front-end!

Join our Discord