🧠 React Concept: Why Closures Cause “Stale State” Bugs Sometimes React code looks correct… but the behavior is confusing. Example 👇 function Counter() { const [count, setCount] = React.useState(0); function handleClick() { setTimeout(() => { console.log(count); }, 2000); } return ( <div> <button onClick={() => setCount(count + 1)}>Increment</button> <button onClick={handleClick}>Log Count</button> </div> ); } Now imagine this: 1️⃣ Click Increment → count becomes 1 2️⃣ Click Log Count 3️⃣ Click Increment again → count becomes 2 After 2 seconds… The console prints: 1 Not 2. 🤔 Why? Because of JavaScript closures. When handleClick runs, it captures the value of count at that moment. React updates state later, but the closure still remembers the old value. ✅ Correct Solution Use a ref to access the latest state. const countRef = useRef(count); useEffect(() => { countRef.current = count; }, [count]); setTimeout(() => { console.log(countRef.current); }, 2000); Now the value stays up-to-date. 🎯 Key Takeaway Many React bugs are not React problems. They are JavaScript closure problems. Understanding this saves hours of debugging. #ReactJS #JavaScript #FrontendDevelopment #ReactHooks #WebDevelopment #CodingTips #LearningInPublic
React Closures Cause Stale State Bugs
More Relevant Posts
-
🔥 Why useEffect Runs Twice in React Strict Mode If you’ve seen this while developing with React: JSX code : useEffect(() => { console.log("Effect ran"); }, []); You expect this to run once. But in development, the console shows: Effect ran Effect ran So… is React broken? Not really. 🧠 What’s Actually Happening When React Strict Mode is enabled, React intentionally runs some lifecycle logic twice in development. This includes useEffect. Why? Because React is checking if your effects are safe and predictable. 🔍 What React Is Testing React wants to detect bugs like: Side effects that are not cleaned up Code that relies on running only once Hidden memory leaks To do that, React: 1️⃣ Mounts the component 2️⃣ Runs the effect 3️⃣ Immediately unmounts it 4️⃣ Mounts it again If your cleanup logic is correct, everything still works. ✅ Example with Cleanup JSX code useEffect(() => { const id = setInterval(() => { console.log("running"); }, 1000); return () => clearInterval(id); }, []); This ensures no leftover side effects. 🎯 Important Note This only happens in development. Production builds run effects normally. #ReactJS #FrontendDevelopment #JavaScript #ReactHooks #WebDevelopment #LearningInPublic
To view or add a comment, sign in
-
🚀 The Event Loop: Browser vs. Node.js 🌐 Ever wondered how JavaScript stays "fast" despite being single-threaded? The secret sauce is the Event Loop. But depending on where your code runs, the Event Loop wears different hats. 🎩 Here is a quick breakdown of how it works on the Client-side vs. the Server-side: 🖥️ 1. JavaScript in the Browser (Client-Side) In the browser, the Event Loop is all about User Experience. The Goal: Keep the UI responsive. How it works: When a user clicks, scrolls, or fetches data, these actions are added to a task queue. The Flow: The Event Loop constantly checks if the Call Stack is empty. If it is, it pushes the next task from the queue to the stack. This ensures that heavy tasks don't "freeze" the screen while rendering. ⚙️ 2. Node.js (Server-Side) In Node.js, the Event Loop is the backbone of High-Concurrency servers. The Goal: Handle thousands of simultaneous requests without blocking. The Heavy Lifters: For "blocking" tasks like File System (FS) or Database operations, the Event Loop offloads the work to Worker Threads (via the Libuv library). The Callback Cycle: 1. The Event Loop registers a callback for an operation. 2. It hands the task to a worker thread. 3. Once the worker is done, it sends the result back to the queue. 4. The Event Loop picks it up and executes the final callback to send the response. 💡 The Bottom Line Whether you are building a snappy UI or a scalable backend, understanding the Event Loop is the difference between a laggy app and a high-performance system. #JavaScript #NodeJS #WebDevelopment #Programming #SoftwareEngineering #TechTips #react #express #next
To view or add a comment, sign in
-
0ms doesn't always mean "now." Understanding JavaScript's hidden priority queue. If you’ve ever used setTimeout(() => {}, 0) to fix a bug, you’ve touched the Event Loop. But for "knowing it works" isn't enough. You need to know why. The Problem: Synchronous "Traffic Jams." JavaScript is single-threaded. If you run a massive for-loop to process 10,000 data points, the browser cannot paint, cannot scroll, and cannot respond to clicks. The app "freezes." The Real-Life Scenario: You’re fetching a massive list of users and need to filter them. If you do this filtering synchronously on the main thread, your "Loading..." spinner will actually stop spinning. The Solution: Task Splitting & Microtasks. 1. Microtasks (Promises/queueMicrotask): These have the highest priority. The browser will drain the entire microtask queue before moving on to anything else. 2. Macrotasks (setTimeout/setInterval): These are lower priority. The browser executes one task, then checks if it needs to re-render the UI. The Trade-off: The "Starvation" Risk. If you recursively call a Microtask, you can "starve" the event loop. Because microtasks always run before the next render, a runaway Promise chain will keep the UI frozen forever. A Macrotask (setTimeout), however, gives the browser a "breather" to paint the screen between tasks. Tip: Use Web Workers for heavy computation, but for UI-related logic splitting, understand your queues. #JavaScript #EventLoop #FrontendArchitecture #ProgrammingTips #SoftwareEngineering #WebDevelopment
To view or add a comment, sign in
-
🚨 I used index as key in React… …and spent HOURS debugging something that made no sense. Everything looked fine at first. Until I: → deleted an item → reordered the list 💥 Suddenly: ❌ Wrong data was displayed ❌ UI behaved randomly ❌ Bugs I couldn’t explain I kept checking my logic. Turns out… the bug wasn’t my logic. 👉 It was THIS: {data.map((item, index) => ( <div key={index}>{item.name}</div> ))}💡 Problem: React uses keys to track identity. When you use index: → identity = position ❌ → not the actual item So when the list changes… React gets confused 😵 ✅ Fix: {data.map((item) => ( <div key={item.id}>{item.name}</div> ))}👉 Stable key = stable UI 💡 Lesson: If your UI feels “random”… check your keys before your logic. Follow me for more such tips ✍️ 👨💻 #ReactJS #Frontend #JavaScript #SoftwareEngineering
To view or add a comment, sign in
-
-
Topic: Stale Closures in React – The Hidden Bug You Don’t See Coming ⚠️ Stale Closures in React – The Bug That Looks Fine… Until It’s Not Your code works. No errors. No warnings. But suddenly… state behaves incorrectly 😐 Welcome to the world of stale closures. 🔹 What is a Stale Closure? When a function captures an old value of state instead of the latest one. 🔹 The Problem const [count, setCount] = useState(0); useEffect(() => { const interval = setInterval(() => { console.log(count); // ❌ always logs old value }, 1000); return () => clearInterval(interval); }, []); 👉 count is stuck at its initial value. 🔹 Why This Happens React closures capture values at render time, not at execution time. 🔹 Solutions ✅ 1. Add dependency useEffect(() => { console.log(count); }, [count]); ✅ 2. Use functional update setCount(prev => prev + 1); ✅ 3. Use useRef for latest value const countRef = useRef(count); countRef.current = count; 💡 Real-World Impact 👉 Timers 👉 WebSockets 👉 Event listeners 👉 Async callbacks 📌 Golden Rule If your logic depends on changing state, make sure it’s not using a stale snapshot. 📸 Daily React tips & visuals: 👉 https://lnkd.in/g7QgUPWX 💬 Have you ever debugged a stale closure issue for hours? 😅 #React #ReactJS #JavaScript #FrontendDevelopment #WebDevelopment #ReactHooks #DeveloperLife
To view or add a comment, sign in
-
𝐆𝐨𝐭 𝐛𝐢𝐭𝐭𝐞𝐧 𝐛𝐲 𝐚 𝐮𝐬𝐞𝐒𝐭𝐚𝐭𝐞 𝐛𝐮𝐠 𝐭𝐡𝐢𝐬 𝐰𝐞𝐞𝐤 𝐭𝐡𝐚𝐭 𝐡𝐚𝐝 𝐦𝐞 𝐬𝐜𝐫𝐚𝐭𝐜𝐡𝐢𝐧𝐠 𝐦𝐲 𝐡𝐞𝐚𝐝 𝐟𝐨𝐫 𝐚𝐧 𝐡𝐨𝐮𝐫. It's easy to fall into the trap of directly updating state based on its current value, like `setCount(count + 1)`. Works fine for simple stuff, right? But in scenarios with multiple rapid updates, or when you're relying on state from a stale closure inside an effect or async operation, you can end up with unexpected results. Your `count` might not be what you think it is. The fix? Use the updater function pattern: ```javascript // Don't do this if 'count' might be stale: // setCount(count + 1); // Do this for reliable updates: setCount(prevCount => prevCount + 1); // Or for complex objects: setUsers(prevUsers => [...prevUsers, newUser]); ``` This ensures your update always receives the latest state snapshot, not the one from when the function was created. It's a small detail, but it can save you from some tricky debugging sessions, especially in React apps with a lot of moving parts. Have you ever run into subtle `useState` issues like this? What's your go-to pattern for complex state updates? #React #JavaScript #Frontend #WebDevelopment #Debugging
To view or add a comment, sign in
-
If you work with JavaScript long enough, you’ll eventually run into situations where a function gets called way too many times. Think about typing in a search bar, scrolling a page, or resizing a browser window. These events fire continuously, and if we trigger heavy logic every single time, the app can become slow pretty quickly. This is where debouncing and throttling come in. Debouncing waits for the user to finish doing something before running the function. A simple example is a search bar. Imagine an API call running on every keystroke while someone types “javascript”. That’s 10 API calls when we really only need one. With debouncing, the function runs only after the user stops typing for a short delay. So instead of triggering the search repeatedly, it waits until the typing pauses. Throttling works a little differently. It makes sure a function runs at most once in a fixed time interval, no matter how many times the event fires. Scrolling is a good example. When a user scrolls, the event can fire dozens of times per second. Throttling limits how often the logic runs, like once every 200ms, which keeps the UI responsive without overwhelming the browser. In simple terms: Debounce → run after the activity stops Throttle → run at regular intervals during the activity Both are small techniques, but they make a big difference when it comes to performance and user experience. #javascript #webdevelopment #frontenddevelopment #fullstackdeveloper #reactjs #devcommunity #programming
To view or add a comment, sign in
-
-
💡React Tip💡 Never pass the setState function directly as a prop to any of the child components like this: const Parent = () => { const [state, setState] = useState({ name: '', age: '' }) . . . return ( <Child setState={setState} /> ) } ✅ The state of a component should only be changed by that component itself. ✅ This ensures your code is predictable. If you pass setState directly to multiple components, it will be difficult to identify from where the state is getting changed. ✅ This lack of predictability can lead to unexpected behavior and make debugging code difficult. ✅ Over time, as your application grows, you may need to refactor or change how the state is managed in the parent component. ✅ If child components rely on direct access to setState, these changes can ripple through the codebase and require updates in multiple places, increasing the risk of introducing bugs. ✅ If sensitive data is part of the state, directly passing setState could potentially expose that data to child components, increasing security risks. ✅ React's component reconciliation algorithm works more efficiently when state and props updates are clearly defined within components. ✅ When child components directly call setState, React may not be able to optimize the rendering process as effectively. Instead of passing setState directly, you can do the following: 1️⃣ Pass data as prop: Pass the data that the child component needs as props, not the setState function itself. This way, you provide a clear interface for the child component to receive data without exposing the implementation details of state. 2️⃣ Pass function as prop: If the child component needs to interact with the parent component's state, you can pass the function as a prop. Declare a function in the parent component and update the state in that function, you can pass this function as a prop to the child component and call it from the child component when needed. 𝗙𝗼𝗿 𝗺𝗼𝗿𝗲 𝘀𝘂𝗰𝗵 𝘂𝘀𝗲𝗳𝘂𝗹 𝗰𝗼𝗻𝘁𝗲𝗻𝘁, 𝗱𝗼𝗻'𝘁 𝗳𝗼𝗿𝗴𝗲𝘁 𝘁𝗼 𝗳𝗼𝗹𝗹𝗼𝘄 𝗺𝗲. #javascript #reactjs #nextjs #webdevelopment
To view or add a comment, sign in
-
🚫 Can We Cancel a Promise in JavaScript? 🎯 Imagine this: An API call is triggered… The user clicks “Cancel” or navigates away… 👉 But the request is still running in the background. Why? Because Promises in JavaScript cannot be cancelled once they start. ⚠️ The Reality A Promise is like a train 🚆 Once it leaves the station, it cannot be stopped midway. ✅ So What Can We Do? Even though we can’t cancel the Promise itself, we can control its behavior 👇 🔹 1. AbortController (Modern Approach) Cancel network requests like fetch: const controller = new AbortController(); fetch('/api/data', { signal: controller.signal }); controller.abort(); // stops the request 🔹 2. Manual Flags (Control Execution) let isCancelled = false; setTimeout(() => { if (!isCancelled) { console.log("Executed"); } }, 2000); isCancelled = true; 🔹 3. (Angular Devs 👀) Use RxJS switchMap() 👉 Automatically cancels previous API calls and keeps only the latest 💡 Key Insight ❌ You can’t cancel a Promise ✅ But you CAN cancel its effect 🚀 Why This Matters This pattern is critical for: API calls Search inputs Rapid user interactions Preventing stale data issues 💬 Let’s Discuss How do you handle cancellation in your apps? 👉 AbortController, RxJS, or custom logic? #JavaScript #Angular #RxJS #AsyncProgramming #Promises #AbortController #FrontendDevelopment #CodingTips #WebDevelopment #TechInterviews
To view or add a comment, sign in
-
-
🟨 𝗝𝗮𝘃𝗮𝗦𝗰𝗿𝗶𝗽𝘁 𝗗𝗮𝘆 𝟱𝟰: 𝗧𝗵𝗲 .sort() 𝗠𝘂𝘁𝗮𝘁𝗶𝗼𝗻 𝗧𝗿𝗮𝗽 (𝗥𝗲𝗮𝗰𝘁 𝗦𝘁𝗮𝘁𝗲 𝗕𝘂𝗴) In JavaScript, .sort() looks harmless — but in React apps it can break your UI with a confusing error. 🔹 𝗧𝗵𝗲 𝗣𝗿𝗼𝗯𝗹𝗲𝗺 𝗜 𝗙𝗮𝗰𝗲𝗱 While rendering a list, I sorted the data directly before mapping. Everything worked… until this error appeared: ❌ 𝘊𝘢𝘯𝘯𝘰𝘵 𝘢𝘴𝘴𝘪𝘨𝘯 𝘵𝘰 𝘳𝘦𝘢𝘥 𝘰𝘯𝘭𝘺 𝘱𝘳𝘰𝘱𝘦𝘳𝘵𝘺 '0' 𝘰𝘧 𝘰𝘣𝘫𝘦𝘤𝘵 '[𝘰𝘣𝘫𝘦𝘤𝘵 𝘈𝘳𝘳𝘢𝘺]' 🔹 𝗪𝗵𝘆 𝗧𝗵𝗶𝘀 𝗛𝗮𝗽𝗽𝗲𝗻𝘀 .sort() mutates the original array. In React: • State and props are treated as immutable • Libraries like Redux / React Query may freeze data • Mutating them directly can cause runtime errors 🔹 𝗧𝗵𝗲 𝗕𝘂𝗴 𝘵𝘳𝘢𝘯𝘴𝘢𝘤𝘵𝘪𝘰𝘯𝘴.𝘴𝘰𝘳𝘵((𝘢, 𝘣) => 𝘯𝘦𝘸 𝘋𝘢𝘵𝘦(𝘣.𝘥𝘢𝘵𝘦) - 𝘯𝘦𝘸 𝘋𝘢𝘵𝘦(𝘢.𝘥𝘢𝘵𝘦)); Here: • transactions came from state/props • .sort() tried to modify it in-place • React blocked the mutation → 💥 error 🔹 𝗧𝗵𝗲 𝗙𝗶𝘅 Always clone before sorting. [...transactions].sort((a, b) => new Date(b.date) - new Date(a.date)); Now: • Original state stays untouched • Sorting happens on a new array • React stays happy ✅ 🔹 𝗠𝘂𝘁𝗮𝘁𝗶𝗻𝗴 𝗠𝗲𝘁𝗵𝗼𝗱𝘀 𝘁𝗼 𝗪𝗮𝘁𝗰𝗵 𝗢𝘂𝘁 𝗙𝗼𝗿 • sort() • reverse() • push() / pop() • splice() 🔹 𝗞𝗲𝘆 𝗧𝗮𝗸𝗲𝗮𝘄𝗮𝘆 .sort() mutates. React state should not. Immutability in React isn't optional — it's the rule. 💬 GitHub example in the comments. #JavaScript #React #Frontend #100DaysOfCode #Day54
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