🪤 The "setState" Trap in React If you think setState updates your value immediately… you’ve got a bug waiting to happen. 👀 🛑 The Scenario: A Simple Checkout A user clicks “Apply Discount” → the price updates → the order is sent to the API. The UI shows the discounted price ✅ The API receives the old price ❌ 🧐 Why does this happen? React state updates are asynchronous. When you call setOrder, React schedules a re-render; it doesn't change the value of your variable mid-execution. In the exact moment you call the setter, your order variable is still a snapshot of the old data. If you send that variable to an API immediately after, you're sending stale data. ✔️ The Solution: Use a Local Constant To ensure your API gets the correct data, create a local reference for the updated state. Use that constant for both the setter and the API call: JavaScript function applyDiscountAndSubmit() { // 1. Create the "next" version of the data const updatedOrder = { ...order, discount: 20, total: order.total - 20 }; // 2. Update the UI setOrder(updatedOrder); // 3. Send the fresh data to the API axios.post("/api/orders", updatedOrder); } 💡 The Takeaway setState doesn’t update your variable; it schedules the next render. If you need to use the "new" state immediately within the same function, don't rely on the state variable. Calculate the value once, store it in a constant, and use that as your source of truth. #React #Frontend #JavaScript #WebDevelopment #SoftwareEngineering
React setState Asynchronous Update Bug Fix
More Relevant Posts
-
🚀 Day 17/30 – Custom Hooks (Deep Dive) Tired of repeating the same logic in multiple components? 🤔 Today I learned how to make React code reusable & clean ⚡ 👉 Custom Hooks Today I learned: ✅ Custom Hooks are reusable functions using React Hooks ✅ They help extract and reuse logic across components ✅ Must always start with "use" (naming convention) --- 💻 Problem: Same logic repeated in multiple components ❌ (e.g. fetching data, form handling) --- 💻 Solution: Create a custom hook ✅ --- 💻 Example: function useCounter() { const [count, setCount] = useState(0); const increment = () => setCount((prev) => prev + 1); const decrement = () => setCount((prev) => prev - 1); return { count, increment, decrement }; } function App() { const { count, increment, decrement } = useCounter(); return ( <> <h2>{count}</h2> <button onClick={increment}>+</button> <button onClick={decrement}>-</button> </> ); } --- 🔥 What actually happens: 1️⃣ Logic is written once inside custom hook 2️⃣ Any component can reuse it 3️⃣ Each component gets its own state --- 💡 Real Use Cases: - API fetching (useFetch) - Form handling (useForm) - Authentication logic - Debouncing input --- ⚡ Advanced Insight: Custom Hooks don’t share state ❌ 👉 They share logic, not data --- 🔥 Key Takeaway: Write logic once → reuse everywhere. Are you still repeating logic or using custom hooks? 👇 #React #CustomHooks #FrontendDevelopment #JavaScript #CleanCode
To view or add a comment, sign in
-
-
𝐈𝐬 𝐲𝐨𝐮𝐫 `𝐮𝐬𝐞𝐄𝐟𝐟𝐞𝐜𝐭` 𝐟𝐢𝐫𝐢𝐧𝐠 𝐰𝐚𝐲 𝐭𝐨𝐨 𝐨𝐟𝐭𝐞𝐧? 𝐘𝐨𝐮 𝐦𝐢𝐠𝐡𝐭 𝐛𝐞 𝐟𝐚𝐥𝐥𝐢𝐧𝐠 𝐟𝐨𝐫 𝐚 𝐜𝐨𝐦𝐦𝐨𝐧 𝐝𝐞𝐩𝐞𝐧𝐝𝐞𝐧𝐜𝐲 𝐚𝐫𝐫𝐚𝐲 𝐭𝐫𝐚𝐩. We've all been there: you put an object or array into your `useEffect`'s dependency array, thinking it's stable. But because JavaScript compares objects and arrays by reference, even if their content is identical, `useEffect` sees a new object on every render and re-runs your effect. This can lead to performance hits, stale data, or even infinite loops. 🚫 The Problem: ```javascript function MyComponent({ data }) { const options = { id: data.id, filter: 'active' }; useEffect(() => { // This runs every render if 'options' object is new fetchData(options); }, [options]); // 'options' is a new object reference each time // ... } ``` ✅ The Fix: Stabilize with `useMemo` If your object or array doesn't logically change across renders (or only changes based on specific primitives), wrap it in `useMemo`. This memoizes the object itself, ensuring its reference remains the same unless its dependencies actually change. ```javascript function MyComponent({ data }) { const stableOptions = useMemo(() => ({ id: data.id, filter: 'active' }), [data.id]); // Only re-create if data.id changes useEffect(() => { fetchData(stableOptions); }, [stableOptions]); // Now only re-runs if stableOptions' reference changes // ... } ``` This trick is a lifesaver for optimizing `useEffect` calls, especially when dealing with complex configurations or filtering logic passed down as props. It keeps your effects clean and your app performant. What's been your biggest `useEffect` headache, and how did you solve it? #React #FrontendDevelopment #JavaScript #Performance #WebDev
To view or add a comment, sign in
-
🚨 The “Invisible” Update: Why Your React UI Might Be Stuck Ever faced a bug where you know the data is there… but your UI just refuses to show it? I recently ran into this while working on a table: Data was fetched successfully ✅ Most columns rendered fine ✅ But one column kept showing empty/null ❌ 🕵️♂️ The Culprit: useRef We were storing incoming async data in useRef. At first glance, everything looked correct: Data was arriving ✔ Ref was updating ✔ But here’s the catch 👇 👉 The column that depended on slightly delayed data never re-rendered 👉 So the UI stayed stuck in its initial empty state ⚠️ Why This Happens useRef: Persists values across renders ✅ Does NOT trigger re-render on update ❌ So even when the data eventually arrived, React had no reason to update the UI. ✅ The Fix: Use useState Switched from useRef → useState const [data, setData] = useState(null); Now: As soon as data updates → component re-renders 🔁 Table updates automatically → no more empty column 🎯 #React #FrontendDevelopment #JavaScript #WebDev #SoftwareEngineering
To view or add a comment, sign in
-
🚀 Stop treating Server State like UI State. As React developers, we’ve all been there: building "custom" fetching logic with useEffect and useState. It starts with one loading spinner and ends with a nightmare of manual cache-busting and race conditions. When I started migrating my data-fetching to TanStack Query, it wasn't just about "fewer lines of code"—it was about a shift in mindset. The Real Game Changers: Declarative vs. Imperative: Instead of telling React how to fetch (and handle errors/loading), you describe what the data is and when it should be considered stale. Focus Refetching: This is a huge UX win. Seeing data update automatically when a user switches back to the tab feels like magic to them, but it’s just one config line for us. Standardized Patterns: It forces the whole team to handle errors and loading states the same way, which makes code reviews much faster. The Win: In a recent refactor, I replaced a tangled mess of global state syncs and manual useEffect triggers with a few useQuery hooks. I was able to delete a significant chunk of boilerplate while fixing those "stale data" bugs that always seem to haunt client-side apps. The takeaway: Don't reinvent the cache. Use tools that let you focus on the product, not the plumbing. 👇 Question for the devs: Are you using TanStack Query for everything, or are you finding that Next.js Server Actions and the native fetch cache are enough for your use cases now? #reactjs #nextjs #frontend #webdev #tanstackquery #javascript
To view or add a comment, sign in
-
Stop using `index` as a key in your React lists just to make the console warning go away. You aren't actually fixing the problem. You are just hiding a potential production bug. React uses the `key` prop as the "source of truth" to track which elements changed, moved, or were deleted during its reconciliation process. It is the unique identity of your component in the virtual DOM. When you use the array index as a key, you are telling React that the "first" item is always the same component instance, regardless of the data it actually holds. This works fine for static lists that never change. But the moment you sort, filter, or remove an item, your UI can go out of sync with your data. If your list item has any internal state, such as an input value or a toggle, that state is tied to the index. If you delete the first item in a list of three, the new first item (which was originally second) will suddenly inherit the state of the deleted item. This happens because React sees that "Key 0" still exists and assumes it can reuse the existing component instance to save on performance. Instead of a simple move, you get a state mismatch that is incredibly hard to debug. It turns your predictable UI into a series of side effects that depend on the order of your array rather than the data itself. The rule is simple. Always use a stable, unique ID from your data. Whether it is a UUID or a database primary key, a stable identity ensures that your renders remain predictable and your component state stays exactly where it belongs. #ReactJS #SoftwareEngineering #WebDevelopment #CodingTips #Javascript #FrontendArchitecture
To view or add a comment, sign in
-
Everything looked correct… but we were sending the wrong data to the backend. At some point, you can started noticing something strange in your dashboard. Nothing was obviously broken. The UI updated. The inputs worked as expected.But the data didn’t match what users were typing. Imagine this - you type “John” into a search field. The UI shows “John”. But the API request… still uses the previous value. Here’s a simplified version of what we had: function Dashboard() { const [filters, setFilters] = React.useState({ search: '' }); const fetchData = React.useCallback(() => { api.get('/users', { params: filters }); }, []); React.useEffect(() => { fetchData(); }, [filters]); return ( <input value={filters.search} onChange={(e) => setFilters({ search: e.target.value }) } /> ); } At first glance, it feels correct. The effect depends on filters. Whenever filters change, we fetch data. So what could go wrong? The issue was hiding in a place that looked “optimized”. That useCallback. It was created once, with an empty dependency array. Which means it captured the value of filters at the very beginning… and never updated it. So every time fetchData ran, it used an old version of the filters. That’s why the UI and the backend slowly drifted apart. The user saw one thing. The API received another. The fix was simple: const fetchData = React.useCallback(() => { api.get('/users', { params: filters }); }, [filters]); Or just removing useCallback entirely. What made this bug tricky is that nothing actually crashed.Everything looked fine. But the data was wrong. It was a good reminder that React doesn’t magically keep values up to date inside functions. Closures remember the state from the moment they were created. And sometimes… that’s exactly the problem. Have you run into something like this before? #reactjs #javascript #frontend #webdevelopment #softwareengineering #react #webdev
To view or add a comment, sign in
-
-
React Performance Tip: Stop Overusing useEffect — Use useQuery Instead One mistake I often see (and made myself earlier) while working with React apps is overusing useEffect for API calls. 👉 Typical approach: Call API inside useEffect Manage loading state manually Handle errors separately Re-fetch logic becomes messy This works… but it doesn’t scale well. 🔁 Better approach: Use React Query (useQuery) When I started using useQuery, it simplified a lot of things: ✅ Automatic caching ✅ Built-in loading & error states ✅ Background refetching ✅ Cleaner and more readable code 👉 Example: Instead of this 👇 useEffect(() => { setLoading(true); axios.get('/api/data') .then(res => setData(res.data)) .catch(err => setError(err)) .finally(() => setLoading(false)); }, []); Use this 👇 const { data, isLoading, error } = useQuery({ queryKey: ['data'], queryFn: () => axios.get('/api/data').then(res => res.data), }); 🔥 Result: Less boilerplate Better performance (thanks to caching) Easier state management 📌 Takeaway: If you're building scalable React applications, tools like React Query are not optional anymore — they’re essential. What’s one React optimization you swear by? Drop it in the comments 👇 #ReactJS #WebDevelopment #Frontend #JavaScript #SoftwareEngineering #CleanCode #TechTips #Developers
To view or add a comment, sign in
-
🚀 How Frontend & Backend Work When We Open a Website in Browser Point 1: Browser Request When we enter a website URL in the browser and press Enter, the browser sends a request to the server where the website is hosted. Point 2: DNS Resolution Before connecting to the website, the browser uses DNS to convert the domain name into an IP address. Example: google.com → server IP address Point 3: Frontend Files Load The server sends the files required to display the UI: HTML → structure CSS → styling JavaScript → functionality images / icons / fonts Point 4: UI Rendering in Browser The browser reads these files and creates the page UI: HTML creates the DOM CSS styles the page JavaScript adds interactivity Point 5: React App Loading In React, the JavaScript bundle loads first, and then React renders components inside the root div. Point 6: Frontend Calls Backend Once the UI is visible, the frontend sends API requests to get dynamic data like user details, products, or orders. Example: fetch('/api/products') Point 7: Backend Processing The backend receives the request, applies business logic, validations, authentication, and other processing. Common technologies: Node.js Java Spring Boot Point 8: Database Interaction The backend fetches or stores data in databases such as: MySQL PostgreSQL MongoDB Point 9: Response to Frontend The backend sends the response back to the frontend in JSON or API response format. Point 10: UI Update The frontend receives the data and updates the UI dynamically without reloading the full page. Complete Flow Browser → Frontend → Backend → Database → Response → UI Update #ReactJS #FrontendDeveloper #Backend #WebDevelopment #JavaScript
To view or add a comment, sign in
-
-
❓ What actually happens when you call fetch('/api')? So I sat down and figured it out. Here's what blew my mind 👇 💡 The JS engine itself is TINY. Just two things inside it: 📦 Memory Heap — where your objects live 📚 Call Stack — tracks what function is running That's it. It can't do timers. It can't make network requests. It can't even listen for a click. 🤯 🎭 So who does all the async work? The BROWSER does. Not JavaScript. ⚙️ Web APIs (written in C++) handle the heavy lifting on separate threads: 🌐 fetch — network requests ⏱️ setTimeout — timers 🖥️ DOM — page manipulation 🖱️ Events — clicks, scrolls, keypresses 💾 LocalStorage, Geolocation, WebSockets… When they finish, they drop callbacks into two queues: 🟢 Microtask Queue (HIGH priority) → Promises, await, queueMicrotask 🔴 Callback Queue (LOW priority) → setTimeout, click, fetch response 🔄 Then the Event Loop steps in: 1️⃣ Is the Call Stack empty? 2️⃣ Drain ALL microtasks first 3️⃣ Run ONE macrotask 4️⃣ Let the browser paint 5️⃣ Repeat forever 🎯 This explains SO much: ✅ Why a heavy loop freezes your page (stack never empties) ✅ Why Promise.then() ALWAYS beats setTimeout(fn, 0) ✅ Why async/await isn't magic — it's just microtask syntax ✅ Why single-threaded doesn't mean single-tasking 👨🍳 My favorite mental model: The JS engine is a single chef. Web APIs are robot assistants running errands in the background. The Microtask Queue is the VIP line. The Callback Queue is the regular line. The Event Loop is the maître d' — but only seats people when the chef is free. 💥 The biggest realization: "JavaScript" the language and "JavaScript" the thing running in your browser are two VERY different things. ✨ The language is small. 🌊 The runtime around it is massive. I mapped the whole thing out with diagrams — call stack traces, V8's Ignition/TurboFan pipeline, the full click-to-fetch-to-DOM lifecycle. Dropping it in the comments 👇 👋 What's something you use every day but never really looked under the hood of? #JavaScript #WebDevelopment #Frontend #V8 #EventLoop #CodeNewbie
To view or add a comment, sign in
-
Who really owns your form data? In a standard HTML input, the DOM is the boss. It holds the value in its own internal memory, and you only "ask" for it when the user hits submit. But in React, we don't like hidden state. We want every piece of data to be explicit and predictable. This is where Controlled Components come in. In this pattern, the React state is the single source of truth. The input doesn't maintain its own value. Instead, you tell the input exactly what to display using the 'value' prop, and you update that value through an 'onChange' handler that modifies the state. The input is "controlled" because its behavior is entirely driven by the React component. Why go through this extra boilerplate? It gives you total coordination over the UI. Since the data lives in your state, you can perform instant field validation, disable the submit button based on specific criteria, or even format the user's input in real-time. There is no "syncing" issue between the DOM and your logic because they are never out of alignment. Of course, controlling every single character stroke in a massive form can feel like overkill. For simple, high-performance scenarios where you just need the data at the end, Uncontrolled Components using 'refs' might be faster. But for most applications, the predictability of a controlled flow far outweighs the cost of a few extra lines of code. It ensures that what the user sees is exactly what your application "knows". #ReactJS #SoftwareEngineering #WebDevelopment #FrontendArchitecture #CodingTips #Javascript
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