Most bugs in production don’t come from complex systems... 💻 They come from simple misunderstandings. Here’s one that even experienced developers occasionally get wrong 👇 🧠 Three snippets. Same intention. Different behavior. // 1 function logValue(value) { if (value === 2) return; console.log(value) } for (let i = 1; i < 5; i++) { logValue(i) } // 2 for (let i = 1; i < 5; i++) { if (i === 2) return; console.log(i) } // 3 [1,2,3,4].forEach((num) => { if (num === 2) return console.log(num) }) 🔍 What’s actually happening? Snippet 1 → Safe abstraction return exits only the function Loop continues Output: 1, 3, 4 Snippet 2 → Dangerous assumption return exits the entire enclosing function Loop stops completely at 2 Output: 1 👉 If this is inside a React component or handler → you just aborted execution. Snippet 3 → Misleading familiarity return exits only the callback, not the loop forEach keeps iterating Output: 1, 3, 4 💡 Takeaway Control flow is not about syntax - it's about execution boundaries. Ask yourself: “What exactly am I returning from?” Function? Loop? Callback? Component? Because JavaScript won’t warn you. It will just… behave correctly in a way you didn’t expect. 🧩 Rule of thumb return in functions → exits function return in forEach → skips current iteration return in loops (top-level) → exits enclosing function (not just loop) The code looks similar. The runtime behavior is not. And that difference is where real-world bugs live. #javascript #reactjs #webdevelopment #softwareengineering #frontend #cleanCode
JavaScript Control Flow Gotchas: Understanding Return Statements
More Relevant Posts
-
𝘂𝘀𝗲𝗘𝗳𝗳𝗲𝗰𝘁 𝗶𝘀 𝗻𝗼𝘁 𝗮 𝗹𝗶𝗳𝗲𝗰𝘆𝗰𝗹𝗲 𝗵𝗼𝗼𝗸. 𝗜𝘁'𝘀 𝗮 𝘀𝘆𝗻𝗰𝗵𝗿𝗼𝗻𝗶𝘀𝗮𝘁𝗶𝗼𝗻 𝘁𝗼𝗼𝗹. ⚠️ Most React bugs start with confusing the two. The lifecycle mindset leads to this: useEffect(() => { fetchUser(userId); }, []); // ❌ stale userId after route change Works in testing. Breaks when userId changes. 𝗡𝗼𝘁 "𝘄𝗵𝗲𝗻 𝘀𝗵𝗼𝘂𝗹𝗱 𝘁𝗵𝗶𝘀 𝗿𝘂𝗻?" 𝗕𝘂𝘁: "𝘄𝗵𝗮𝘁 𝘀𝗵𝗼𝘂𝗹𝗱 𝘁𝗵𝗶𝘀 𝘀𝘁𝗮𝘆 𝗶𝗻 𝘀𝘆𝗻𝗰 𝘄𝗶𝘁𝗵?" useEffect(() => { document.title = user.name; // Keeps document title in sync with user.name }, [user.name]); Same result. Completely different mental model — and completely different bugs. Effects don't control time. They react to state. 𝗪𝗵𝘆 𝘁𝗵𝗶𝘀 𝗺𝗮𝘁𝘁𝗲𝗿𝘀 𝗶𝗻 𝗽𝗿𝗼𝗱𝘂𝗰𝘁𝗶𝗼𝗻: 1️⃣ 𝗘𝗺𝗽𝘁𝘆 𝗱𝗲𝗽𝗲𝗻𝗱𝗲𝗻𝗰𝘆 𝗮𝗿𝗿𝗮𝘆𝘀 𝗵𝗶𝗱𝗲 𝗿𝗲𝗮𝗹 𝗱𝗲𝗽𝗲𝗻𝗱𝗲𝗻𝗰𝗶𝗲𝘀 [] does mean "run on mount." But it also means "this effect has no external dependencies." If that second part is a lie — you get stale data that looks correct in testing but fails in production. 2️⃣ 𝗘𝗳𝗳𝗲𝗰𝘁𝘀 𝘁𝗵𝗮𝘁 𝗱𝗼 𝘁𝗼𝗼 𝗺𝘂𝗰𝗵 𝗮𝗿𝗲 𝗮 𝗱𝗲𝘀𝗶𝗴𝗻 𝘀𝗺𝗲𝗹𝗹 One useEffect fetching data, updating the DOM, and setting state? That's three synchronisation concerns. Split it: useEffect(() => { fetchUser(); }, [userId]); useEffect(() => { document.title = user.name; }, [user.name]); 3️⃣ 𝗠𝗼𝘀𝘁 𝘂𝘀𝗲𝗘𝗳𝗳𝗲𝗰𝘁 𝗯𝘂𝗴𝘀 𝗮𝗿𝗲 𝗱𝗲𝗽𝗲𝗻𝗱𝗲𝗻𝗰𝘆 𝗮𝗿𝗿𝗮𝘆 𝗯𝘂𝗴𝘀 Not because developers forgot a dependency. Because they were thinking about timing instead of synchronisation — and added [] to silence re-renders instead of fixing the dependency. ⚠️ When the linter flags a missing dependency — it's not being pedantic. It's telling you your mental model is wrong. 🎯 𝗧𝗵𝗲 𝗧𝗮𝗸𝗲𝗮𝘄𝗮𝘆 Every useEffect should complete this sentence: "This effect keeps [X] in sync with [Y]." If you can't complete it — the effect doesn't belong there. 💬 What's a useEffect bug that only showed up in production? Drop it below. 👇 #ReactJS #SoftwareEngineering #WebDev #FrontendEngineering #JavaScript
To view or add a comment, sign in
-
-
⚡ Why doesn’t setTimeout(fn, 0) run immediately? Most developers think JavaScript executes things in order… but that’s not always true. Let’s break it Example: console.log("Start"); setTimeout(() => console.log("Timeout"), 0); Promise.resolve().then(() => console.log("Promise")); console.log("End"); Output: Start End Promise Timeout What’s happening? JavaScript uses something called the Event Loop to handle async operations. Here’s the flow: Code runs in the Call Stack Async tasks go to Web APIs Completed tasks move to queues Event Loop pushes them back when stack is empty The twist: Microtasks (HIGH PRIORITY) • Promise.then() • queueMicrotask() Macrotasks (LOWER PRIORITY) • setTimeout() • setInterval() That’s why: Promise executes BEFORE setTimeout — even with 0ms delay Real takeaway: Understanding this can help you debug tricky async issues, optimize performance, and write better code. Have you ever faced a bug because of async behavior? #JavaScript #WebDevelopment #Frontend #Programming #Coding #Developers #100DaysOfCode
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
-
-
🚀 Day 5/30 — Async/Await changed JavaScript forever Before async/await, we wrote: 𝘭𝘰𝘨𝘪𝘯𝘜𝘴𝘦𝘳() .𝘵𝘩𝘦𝘯(𝘨𝘦𝘵𝘖𝘳𝘥𝘦𝘳𝘴) .𝘵𝘩𝘦𝘯(𝘱𝘳𝘰𝘤𝘦𝘴𝘴𝘗𝘢𝘺𝘮𝘦𝘯𝘵) .𝘤𝘢𝘵𝘤𝘩(𝘩𝘢𝘯𝘥𝘭𝘦𝘌𝘳𝘳𝘰𝘳) Worked well… But async/await made asynchronous code feel natural: 𝘵𝘳𝘺 { 𝘤𝘰𝘯𝘴𝘵 𝘶𝘴𝘦𝘳 = 𝘢𝘸𝘢𝘪𝘵 𝘭𝘰𝘨𝘪𝘯𝘜𝘴𝘦𝘳(); 𝘤𝘰𝘯𝘴𝘵 𝘰𝘳𝘥𝘦𝘳𝘴 = 𝘢𝘸𝘢𝘪𝘵 𝘨𝘦𝘵𝘖𝘳𝘥𝘦𝘳𝘴(𝘶𝘴𝘦𝘳.𝘪𝘥); 𝘢𝘸𝘢𝘪𝘵 𝘱𝘳𝘰𝘤𝘦𝘴𝘴𝘗𝘢𝘺𝘮𝘦𝘯𝘵(𝘰𝘳𝘥𝘦𝘳𝘴); } 𝘤𝘢𝘵𝘤𝘩(𝘦𝘳𝘳){ 𝘤𝘰𝘯𝘴𝘰𝘭𝘦.𝘦𝘳𝘳𝘰𝘳(𝘦𝘳𝘳); } Cleaner. Easier to debug. Easier to maintain. 𝐁𝐮𝐭 𝐡𝐞𝐫𝐞’𝐬 𝐭𝐡𝐞 𝐦𝐢𝐬𝐭𝐚𝐤𝐞 𝐦𝐚𝐧𝐲 𝐝𝐞𝐯𝐞𝐥𝐨𝐩𝐞𝐫𝐬 𝐦𝐚𝐤𝐞👇 await getUsers(); await getOrders(); await getProducts(); ❌ Slow (runs sequentially) Better: await Promise.all([ getUsers(), getOrders(), getProducts() ]); ✅ Concurrent + faster 💡 Big lesson: Async/Await improved readability. Promise.all() improves performance. Small code decisions create big scalability differences. What do you prefer in production: Async/Await or .then() chains? #NodeJS #JavaScript #AsyncAwait #BackendDevelopment #SoftwareEngineering
To view or add a comment, sign in
-
-
Are You Using Hooks or Misusing Them? Hooks made React cleaner but only if you respect the rules. In production environments, most bugs don't stem from complex business logic; they stem from subtle anti-patterns that degrade performance and scalability. If you’re aiming for senior-level code, here are the patterns you should stop today: ⚠️ 1. The useEffect Crutch If a value can be computed during render, it doesn’t belong in an effect. Effects are for synchronization with external systems, not for transforming data. Overusing them leads to unnecessary re-renders and "race condition" bugs. ⚠️ 2. Suppressing Dependency Arrays Disabling ESLint warnings is like ignoring a "Check Engine" light. If including a dependency breaks your logic, your logic is flawed, not the rule. Fix the stale closure; don't hide it. ⚠️ 3. Storing Derived State Storing data in useState that can be calculated from props or other state variables is a recipe for sync issues. Always maintain a Single Source of Truth. ⚠️ 4. Abstraction Fatigue (Custom Hook Overkill) Not every 3-line logic block needs a custom hook. Premature abstraction often makes code harder to follow than simple, localized duplication. Abstract for reusability, not just for "cleaner" looking files. ⚠️ 5. Using Hooks to Mask Architectural Debt Hooks are powerful, but they won't fix a poorly structured component tree. Clean architecture > "Clever" hook implementations. 💡 Senior Dev Mindset: Hooks are not just features; they are constraints that enforce predictable behavior. If your React codebase feels "fragile," it’s rarely a React problem it's usually a Hook implementation problem. 💬 Curious to hear from the community: Which of these "subtle" bugs have you spent the most time debugging lately? #ReactJS #FrontendArchitecture #WebDevelopment #JavaScript #SoftwareEngineering #CleanCode #ReactHooks #SeniorDeveloper #CodeQuality #ProgrammingTips
To view or add a comment, sign in
-
I recently ran into a production bug that didn’t make sense at first. The code looked correct. The logic was sound. And yet… execution order was completely off. After digging deeper, the issue wasn’t the code itself — it was how the browser was scheduling it. That’s when I had to go back to fundamentals: the Event Loop. At the core of browser execution are 4 moving parts: 🔹 Call Stack – synchronous execution 🔹 Web APIs – timers, network, DOM events 🔹 Task Queue – macrotasks 🔹 Microtask Queue – Promises, MutationObserver 🎯 The root cause? A Promise callback was executing before a timer-based callback — even though the timer had 0 delay. Because: 👉 All microtasks run before the next macrotask. That small detail caused a race condition where state was being updated earlier than expected — breaking the flow. 💡 Fixing it required: • Rethinking execution order (not just code order) • Moving critical logic into the correct queue • Ensuring state updates aligned with the event loop cycle This wasn’t just a “bug fix” — it was a reminder: 🔁 If something feels off in async JavaScript, don’t just debug the code — debug the event loop. Once you see it, everything clicks. --- ♻️ Repost if you’ve ever chased a “ghost bug” in async JS 💬 Comment: What’s the trickiest async issue you’ve debugged? #JavaScript #EventLoop #AsyncProgramming #WebDevelopment #Frontend #SoftwareEngineering #Coding #Debugging #JS #WebPerformance #Developers
To view or add a comment, sign in
-
-
Nobody told me this when I started React. I learned props. I learned the state. I thought I understood both. I didn't. I was putting everything in state. User data. Config values. Things passed in from the parent. Didn't matter — if I needed it inside a component, it went into useState. It worked. Until it didn't. On a client project, I had a component receiving a userId from its parent. I was also storing that userId in local state. Then the parent updated. My local state didn't. Two different values. One component. Complete mess. The bug took me hours to find. The fix was deleting four lines of code. Here's what nobody told me: Props and state are not two ways to store data. They are two completely different things with two completely different jobs. Props are data that comes from outside. The parent owns it. The parent controls it. Your component just receives it and uses it. You don't store it. You don't copy it. You use it directly. State is data that lives inside. Your component owns it. Your component controls it. When it changes, the component re-renders. Nothing outside knows it exists unless you explicitly pass it down. One simple test I use now: Does this component own this data — or is it just receiving it from somewhere else? If it owns it → state. If it's receiving it → props. Use it directly. Never copy it into state. That one question has saved me from every props-vs-state bug I've ever faced. The bug I had on that client project? I was copying props into the state. The parent updated the prop. My state copy didn't follow. UI showed stale data. Classic mistake. Extremely common. Nobody warns you about it early enough. #React #JavaScript #Frontend #ReactJS #WebDevelopment #Programming #100DaysOfCode #SoftwareDevelopment
To view or add a comment, sign in
-
-
Only 2% of developers use Full-stack TypeScript with tRPC for true end-to-end type safety. Have you ever wondered why, despite the evolution in tooling and frameworks, bugs still crawl into your codebase after every release? As a developer who's spent countless late nights debugging mysteriously broken interfaces, I’ve turned to Full-stack TypeScript with tRPC for a solution. Type safety isn't just a buzzword; it translates to real-world stability and confidence in code. TypeScript ensures your data contracts remain intact across your entire stack. But here's the kicker: tRPC elevates this synergy to a level where type errors become almost a non-issue. By generating API types directly from your server-side logic, every part of your application - backend to frontend - remains synchronized automatically. Imagine making a server-side change and your editor flagging exactly where you need to adjust your client logic. It's not just time-saving; it's transformative. I remember using vibe coding to quickly prototype features, and it was liberating to see real-time type validations catch potential runtime errors before they became problems. Here's a quick example of how simple it is to define a type-safe API with tRPC: ```typescript import { initTRPC } from '@trpc/server'; const t = initTRPC.create(); export const appRouter = t.router({ greeting: t.procedure .input((val: string) => val.trim()) .query(({ input }) => `Hello ${input}`), }); export type AppRouter = typeof appRouter; ``` This isn't just about using TypeScript; it's about leveraging its full potential to enhance our development workflow. What are your thoughts on adopting full-stack type safety? Are you already using something like tRPC, or is there another framework you find indispensable? Let’s dive into the discussion! #WebDevelopment #TypeScript #Frontend #JavaScript
To view or add a comment, sign in
-
-
💁 Var, Let, or Const? Stop the Confusion! Choosing the right variable declaration in JavaScript is more than just a syntax choice—it's about writing predictable and bug-free code. If you are still reaching for var by habit, here is why you might want to reconsider. Let’s break down the "Big Three" across three critical dimensions: 1️⃣ Scope: Where does your variable live? - var: Function-scoped. It doesn't care about block levels like if or for loops. It leaks! - let & const: Block-scoped. They stay strictly within the curly braces {} where they are defined. This prevents accidental data leaks and collisions. 2️⃣ Hoisting: The "Magic" behavior - var: Hoisted and initialized as undefined. You can access it before the line it’s written (though it’s usually a bad idea). - let & const: Also hoisted, but they enter the Temporal Dead Zone (TDZ). Accessing them before declaration triggers a ReferenceError. 3️⃣ Reassignment & Redeclaration - var is the most "relaxed"—you can redeclare and reassign it anywhere, which often leads to accidental bugs. - let allows you to change the value (reassign) but forbids you from redeclaring the same variable in the same scope. - const is the strictest. No reassignment, no redeclaration. Once it’s set, it’s locked (though you can still mutate object properties!). 💡 My rule: Use const by default and let only when change is necessary. Forget var—modern JavaScript is all about block-scoping and reliability. Did I miss anything? How do you decide which one to use in your daily workflow? Let’s discuss below! 👇 #JavaScript #CodingTips #CleanCode #WebDev #Frontend #Programming
To view or add a comment, sign in
-
Explore related topics
- Coding Best Practices to Reduce Developer Mistakes
- Idiomatic Coding Practices for Software Developers
- Clear Coding Practices for Mature Software Development
- How to Add Code Cleanup to Development Workflow
- Keeping Code DRY: Don't Repeat Yourself
- Building Clean Code Habits for Developers
- How to Improve Your Code Review Process
- GitHub Code Review Workflow Best Practices
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