I wasn't trying to learn about keys. I was going deep into React's reconciliation algorithm - how the fiber tree diffs, why React bets on O(n) with positional heuristics, what "reuse" actually means at the node level. Keys came up as a consequence of that, not as a topic on their own. So I built a small demo to feel the difference instead of just knowing it: A draggable list. Each row has local input state. Reorder without stable keys - the label moves, the typed text doesn't. React mapped state by position, not identity. The state wasn't lost. It was just attached to the wrong fiber node. Switch to key={item.id} — state follows the item through every reorder. React now has an identity contract to reconcile against. That's the actual mechanism. Not a rule. A direct consequence of how the diffing heuristic works. Going to the source of something and letting the rules fall out naturally - that's the only way I retain things long-term. #React #Frontend #JavaScript #ReactInternals
React Fiber Tree Diffs and Keys
More Relevant Posts
-
Using index as a key is dangerous Every React developer has written this at least once. items.map((item, index) => ( <li key={index}>{item}</li> )) Looks fine. Works fine. But it isn't This is Post 5 of the series: 𝗥𝗲𝗮𝗰𝘁 𝗨𝗻𝗱𝗲𝗿 𝘁𝗵𝗲 𝗛𝗼𝗼𝗱 Where I explain what React is actually doing behind the scenes. Here's what actually happens when you use index as key: You delete one item from a list. React doesn't know which item was removed. It just looks at positions. So it re-renders everything from that index downward. Input states get mismatched. Animations break. Bugs appear that you can't even reproduce consistently. And... No error. Just... wrong behavior. 🔑 Here's what React actually needs: A key isn't just something unique. It needs to be stable, unique, AND tied to the data — not the position. ❌ key={index} → breaks on delete, sort, filter ❌ key={Math.random()} → new key every render = React destroys and recreates the node ✅ key={item.id} → stable, reliable, React knows exactly who is who The rule is simple: If your list can ever be reordered, filtered, or deleted from... index as key will silently break your UI. Use your data's ID. If it doesn't have one, generate it at creation — not during render. const newItem = { id: crypto.randomUUID(), name: "New Task" } One tiny prop. Massive impact on how React tracks your entire list. In Post 6 of React Under the Hood: What Happens When You Call setState Follow Farhaan Shaikh if you want to understand react more deeply. 👉 Read the previous post - Understanding diffing algorithm: https://lnkd.in/dzW3NP_V #SoftwareEngineering #ReactJS #WebDevelopment #JavaScript #FrontendDevelopment #BuildInPublic #LearnInPublic #ReactUnderTheHood
To view or add a comment, sign in
-
If you’re writing 5 files just to toggle a boolean... 🛑 You’re not scaling. You’re over-engineering. For a long time, I used Redux for almost everything in React. And honestly? It felt powerful... but also unnecessarily complex for 90% of my use cases. Recently, I switched to Zustand — and the difference is 🔥 Why Zustand just makes sense: ✅ Zero Boilerplate No Providers. No massive folder structures. Just create and use. ✅ Hook-Based If you know useState, you already understand Zustand. It feels like native React. ✅ Performance First It handles selective re-renders out of the box. Only the components that need the data will update. 💻 The "Store" is this simple: JavaScript import { create } from 'zustand' const useStore = create((set) => ({ count: 0, inc: () => set((state) => ({ count: state.count + 1 })), })) Use it anywhere: JavaScript function Counter() { const { count, inc } = useStore() return <button onClick={inc}>{count}</button> } ⚡ 𝗣𝗥𝗢 𝗠𝗢𝗩𝗘 (Most developers miss this): Use selectors to grab only what you need: const count = useStore((state) => state.count) This keeps your app lightning-fast even as your state grows massive. 📈 Since switching, my code is: → Simpler → Cleaner → Easier to maintain 🟣 Team Redux (The tried and true) 🐻 Team Zustand (The minimalist) #ReactJS #Zustand #JavaScript #WebDevelopment #Frontend #CodingTips #SoftwareEngineering
To view or add a comment, sign in
-
-
For years, sorting an array in JavaScript has been a source of subtle bugs. The `.sort()` method, while functional, mutates the original array in place. This often leads developers to create a copy first, usually with the spread operator `[...]`, before sorting. This "copy-then-sort" pattern is verbose and easily forgotten, especially in complex applications where arrays are passed around. If you forget the copy, you inadvertently modify data in other parts of your program, leading to hard-to-trace bugs and unexpected side effects that can really tank your productivity. Enter `Array.toSorted()`. This modern, immutable alternative returns a new sorted array without touching the original. It's cleaner, safer, and exactly what developers have needed for handling data integrity. It prevents accidental data corruption and makes your code much more predictable. Are you still writing it the old way? #javascript #webdevelopment #frontend #cleancode #js
To view or add a comment, sign in
-
-
𝐈𝐬 𝐲𝐨𝐮𝐫 `𝐮𝐬𝐞𝐄𝐟𝐟𝐞𝐜𝐭` 𝐫𝐮𝐧𝐧𝐢𝐧𝐠 𝐰𝐡𝐞𝐧 𝐢𝐭 𝐬𝐡𝐨𝐮𝐥𝐝𝐧'𝐭? 𝐓𝐡𝐞 𝐜𝐮𝐥𝐩𝐫𝐢𝐭 𝐦𝐢𝐠𝐡𝐭 𝐛𝐞 𝐦𝐨𝐫𝐞 𝐬𝐮𝐛𝐭𝐥𝐞 𝐭𝐡𝐚𝐧 𝐲𝐨𝐮 𝐭𝐡𝐢𝐧𝐤. I just spent a frustrating hour debugging a seemingly random data refetch in a React component, only to trace it back to a non-primitive dependency in my `useEffect` array. When you pass an object or a function created inside your component directly into `useEffect`'s dependency array, React performs a reference equality check. Even if the contents of your object or the logic of your function haven't changed, its reference is new on every render. This forces your effect to re-run unnecessarily. Here's the common trap: ```javascript // 🚨 Problematic: 'config' object reference changes on every render const MyComponent = ({ id }) => { const config = { userId: id, status: 'active' }; useEffect(() => { fetchData(config); }, [config]); // 💥 Effect re-runs even if 'id' hasn't changed // ... }; ``` A cleaner, more performant way is to stabilize those references. For configuration objects, `useMemo` is your friend: ```javascript // ✅ Solution: 'memoizedConfig' reference is stable as long as 'id' is const MyComponent = ({ id }) => { const memoizedConfig = useMemo(() => ({ userId: id, status: 'active' }), [id]); useEffect(() => { fetchData(memoizedConfig); }, [memoizedConfig]); // ... }; ``` This prevents wasted renders and unnecessary side effects, keeping your app snappier and less buggy. It's often the small details in `useEffect` that lead to the biggest headaches! Have you ever battled a similar `useEffect` dependency bug? What was your fix? #ReactJS #FrontendDevelopment #JavaScript #WebDev #ReactHooks
To view or add a comment, sign in
-
React recap: 𝗨𝘀𝗶𝗻𝗴 𝗶𝗻𝗱𝗲𝘅 𝗮𝘀 𝗮 𝘂𝗻𝗶𝗾𝘂𝗲 𝗜𝗗 𝘄𝗮𝘀 𝗺𝘆 𝗯𝗶𝗴𝗴𝗲𝘀𝘁 𝗺𝗶𝘀𝘁𝗮𝗸𝗲 𝗶𝗻 𝗥𝗲𝗮𝗰𝘁. At first, it felt harmless. items.map((item, index) => ( <Component key={index} /> )) Everything worked… until it didn’t. Here’s what I learned the hard way: • When the list changes (add/remove/reorder), React gets confused • Components don’t re-render correctly • State sticks to the wrong items (this one is scary) • Bugs appear that make zero sense at first I spent hours debugging something that wasn’t even obvious. The real problem? Index is not a stable identity. So what should we do instead? ✔️ Use a unique ID from your data (database ID, UUID, etc.) ✔️ Generate stable IDs (not on every render) ✔️ Think of keys as identity, not position Bad: key={index} Good: key={item.id} Simple change. Massive difference. One small mistake can quietly break your entire UI logic. If you're using index as key — fix it before it fixes you. #React #Frontend #WebDevelopment #JavaScript #CodingLessons
To view or add a comment, sign in
-
-
Most developers still deep clone objects like this: JSON.parse(JSON.stringify(data)) It works. Until it doesn't. Dates become strings. Functions vanish. undefined disappears silently. Circular references throw an error. There's a native alternative that actually handles these cases — and most developers don't know it exists. One caveat: structuredClone() doesn't clone functions or class instances — it's designed for data, not behavior. But for 90% of real-world cases, that's exactly what you need. Available natively in all modern browsers and Node.js 17+ — no library required. Are you still using JSON tricks for deep cloning? 👇 #JavaScript #WebDevelopment #Frontend #JS #SoftwareEngineering
To view or add a comment, sign in
-
-
I found a hidden React performance issue… without using any profiler. It was caused by something most developers ignore: 👉 “Referential equality” Here’s the problem 👇 I had a component like this: const items = [{ id: 1 }, { id: 2 }]; return <List data={items} />; Looks harmless. But on every render, a NEW array is created ❌ Even if the data is the same. So React sees: old !== new → re-render Now imagine this passed into: - memoized components - useEffect dependencies - expensive lists 🚨 Everything re-runs unnecessarily --- 👉 Real fix: const items = useMemo(() => [{ id: 1 }, { id: 2 }], []); return <List data={items} />; Now: Same reference → no unnecessary re-renders ✅ --- 💡 Where this secretly breaks apps: 1️⃣ React.memo doesn’t work as expected 2️⃣ useEffect runs again and again 3️⃣ Large lists become slow --- ⚠️ The insight most people miss: React doesn’t compare values deeply It compares references (===) Even identical objects/arrays are “different” if recreated --- 🎯 My takeaway: Performance isn’t just about “big code” It’s about small invisible patterns Once you understand this, you start writing React very differently. --- Next time your optimization “doesn’t work” Check references… not logic. --- Have you ever debugged something like this? #ReactJS #JavaScript #FrontendDevelopment #WebPerformance #ReactPerformance #SoftwareEngineering #FullStackDeveloper #CleanCode #Frontend #WebDevelopment #CodingTips #Developers #Programming #TechLearning #LearnInPublic
To view or add a comment, sign in
-
How I Understood Memory Leak in JavaScript One day I wrote this small code: let user = { name: "Siddharth" }; let map = new Map(); map.set(user, "Developer"); user = null; console.log(map); And I thought: 👉 “I removed the user… so memory should be free now.” But I was wrong. 🧠 What actually happened? Even after: user = null; The object was still in memory. Why? Because Map was still holding a reference to it. 👉 JavaScript says: “As long as something is pointing to this object, I won’t delete it.” That’s called a memory leak. 💡 Human way to understand this Imagine: You throw something in the dustbin 🗑️ But someone secretly keeps a copy of it. So it’s not really gone. That’s exactly what Map does here. ⚠️ The problem If this keeps happening in a real app: • Memory keeps increasing 📈 • App becomes slow 🐢 • Eventually crashes 💥 ✅ The fix (cleanup) let user = { name: "Siddharth" }; let map = new Map(); map.set(user, "Developer"); user = null; // Cleanup map.clear(); console.log(map); // Map(0) {} Now: 👉 No reference → memory gets freed 🚀 The lesson I learned 📌 Memory leaks happen when references are not removed 📌 Map keeps strong references 📌 Always clean up unused data Now whenever I use Map, I ask: 👉 Am I removing things I no longer need? Still learning JavaScript the human way. 🚀 #JavaScript #MemoryLeak #WebDevelopment #LearningInPublic #CleanCode #ReactJS #FrontendDevelopment #DeveloperJourney #Performance
To view or add a comment, sign in
-
-
I thought I understood JavaScript's event loop. I didn't. Today I went deep into libuv — the C library that actually powers Node.js under the hood. And it completely changed how I think about async code. Here's what clicked: The event loop isn't one thing. It has 4 distinct phases that run in order — every single tick: ⏱ Timers — runs setTimeout / setInterval callbacks whose delay has expired. 📡 Poll — fetches new I/O events, executes I/O callbacks. ✅ Check — runs setImmediate callbacks. 🔒 Close — handles closed connections and cleanup callbacks. But here's the part that blew my mind — Before each phase, the event loop checks an inner priority cycle. Microtasks (process.nextTick, Promises) get processed first. Every time. No exceptions. So that "random" order your async callbacks fire in? Not random at all. It's a deterministic, phase-driven machine running underneath every Node.js app you've ever built. I also got my first look at the thread pool — libuv's way of handling heavy tasks (file I/O, DNS, crypto) off the main thread. Can't wait to go deeper there. All of this from Namaste Node.js, Thanks to Akshay Saini. If you're serious about backend JavaScript, this course is the real deal. As a frontend dev, understanding the runtime at this level makes me a sharper engineer — not just someone who writes components, but someone who understands why the code behaves the way it does.
To view or add a comment, sign in
-
𝗟𝗲𝘁’𝘀 𝘁𝗮𝗹𝗸 𝗮 𝗹𝗶𝘁𝘁𝗹𝗲 𝗯𝗶𝘁 𝗮𝗯𝗼𝘂𝘁 𝗡𝗼𝗱𝗲.𝗷𝘀! 𝐓𝐨𝐩𝐢𝐜 𝟏: 𝐓𝐡𝐞 𝐍𝐨𝐝𝐞.𝐣𝐬 𝐄𝐯𝐞𝐧𝐭 𝐋𝐨𝐨𝐩 It’s a meticulously ordered cycle of 6 steps - and most developers have never seen the part that goes between each one. ⚙️ 𝘛𝘩𝘦 6 𝘚𝘵𝘦𝘱𝘴: 1️⃣ 𝘛𝘪𝘮𝘦𝘳𝘴: Recalls setTimeout / setInterval whose delay has passed 2️⃣ 𝘈𝘸𝘢𝘪𝘵𝘪𝘯𝘨 callbacks: Recalls I/O errors that were rejected from the previous iteration 3️⃣ 𝘗𝘰𝘭𝘭𝘪𝘯𝘨: Retrieves new I/O events. This is where Node.js waits when idle. 4️⃣ 𝘊𝘩𝘦𝘤𝘬: setImmediate callbacks, always after Poll 5️⃣ 𝘊𝘭𝘰𝘴𝘦 𝘊𝘢𝘭𝘭𝘣𝘢𝘤𝘬𝘴: socket.on('close'), cleanup handlers 💠The hidden layer: microtasks Between each step, before the loop progresses, Node.js completely empties the microtask queue. Two subqueues, processed in exact order: ➡️ process.nextTick() callbacks - always first ➡️ Promise resolution callbacks - second This means that microtasks have a higher priority than any step of the Event Loop. 📌 𝘛𝘩𝘦 𝘳𝘶𝘭𝘦𝘴 𝘰𝘧 𝘵𝘩𝘶𝘮𝘣: ➡️ process.nextTick() is fired before Promises, even if Promise resolved first. ➡️ setImmediate() is always fired after I/O callbacks in the same iteration. ➡️ The order of setTimeout(fn, 0) and setImmediate() is not deterministic outside of I/O callbacks. ➡️ Never use nextTick() recursively in production code. The event loop is why Node.js can handle thousands of simultaneous connections on a single thread. Controlling its execution order is the difference between writing asynchronous code and understanding it. #nodejs #javascript #backend #eventloop #softwareengineering #webdevelopment
To view or add a comment, sign in
-
Explore content categories
- Career
- Productivity
- Finance
- Soft Skills & Emotional Intelligence
- Project Management
- Education
- Technology
- Leadership
- Ecommerce
- User Experience
- Recruitment & HR
- Customer Experience
- Real Estate
- Marketing
- Sales
- Retail & Merchandising
- Science
- Supply Chain Management
- Future Of Work
- Consulting
- Writing
- Economics
- Artificial Intelligence
- Employee Experience
- Workplace Trends
- Fundraising
- Networking
- Corporate Social Responsibility
- Negotiation
- Communication
- Engineering
- Hospitality & Tourism
- Business Strategy
- Change Management
- Organizational Culture
- Design
- Innovation
- Event Planning
- Training & Development