<!-- mobian-agent-page publisher="dailydev" canonical="https://daily.dev/posts/react-for-vue-developers-2-state-effects-re-renders-lf4kx00ba" -->

---
title: React for Vue Developers, 2: State, Effects, Re-renders
description: This second installment of a series translating React concepts for Vue developers explains why React re-renders differently from Vue: React reruns the entire...
canonical: https://daily.dev/posts/react-for-vue-developers-2-state-effects-re-renders-lf4kx00ba
twitter:card: summary_large_image
twitter:site: @dailydotdev
og:type: website
og:site_name: daily.dev
og:title: React for Vue Developers, 2: State, Effects, Re-renders | daily.dev
og:description: This second installment of a series translating React concepts for Vue developers explains why React re-renders differently from Vue: React reruns the entire...
og:url: https://daily.dev/posts/react-for-vue-developers-2-state-effects-re-renders-lf4kx00ba
og:image: https://api.daily.dev/og/posts/Lf4kX00bA.png
og:image:alt: React for Vue Developers, 2: State, Effects, Re-renders
og:image:width: 1200
og:image:height: 630
og:locale: en
---

> ## Documentation Index
> Fetch the complete documentation index at: https://daily.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# React for Vue Developers, 2: State, Effects, Re-renders

**[Telerik](https://daily.dev/sources/telerik)** · 11 min read · 12 upvotes · 2 comments

## Summary

This second installment of a series translating React concepts for Vue developers explains why React re-renders differently from Vue: React reruns the entire component function on state changes, while Vue tracks dependencies and updates the DOM surgically. It covers useState (value plus setter, replace-not-mutate semantics, stale closures, and the functional updater form), useEffect as React's unified equivalent of Vue's onMounted, watch, and watchEffect (with manual dependency arrays instead of automatic tracking), and useRef as a mutable, render-skipping storage mechanism analogous to plain variables or untracked refs in Vue. Side-by-side Vue/React code examples illustrate each concept, including the classic stale closure bug in a timer effect.

## Full article

daily.dev links to this article rather than hosting it. Read it at the original source: <https://www.telerik.com/blogs/react-vue-developers-part-2-state-effects-why-react-re-renders-differently>

## Questions this post answers

### why does calling setCount twice in a row in React only increment the count by 1 instead of 2

Because the state variable is a constant snapshot captured for that specific render, so both calls read the same value, compute the same result, and overwrite each other. The fix is the functional updater form, such as setCount(c => c + 1), which receives the latest pending value instead of the stale render snapshot. This is the recommended approach whenever new state depends on previous state.

_Developers debugging stale state bugs in React can find clear before-and-after examples via daily.dev._

### why does my setInterval callback in a React useEffect keep using an old value of my state variable

This happens because the interval callback closes over the state variable's value from the render in which the effect ran, and that value never updates if the effect only runs once (empty dependency array). For example, a counter interval will increment once and then freeze, always computing 0 + 1. The fix is to use the functional updater form of the setter, which avoids reading the stale closed-over value entirely.

_When chasing stale closure bugs in React effects, daily.dev surfaces practical debugging explanations._

### what is the difference between useEffect and useLayoutEffect compared to Vue's onMounted

Vue's onMounted runs after the DOM is in place but before the browser paints, while React's useEffect runs after paint, making it invisible for tasks like fetching data or focusing an input. When layout must be measured or adjusted before the user sees it, useLayoutEffect is the closer match to onMounted's timing, since it also runs before paint.

_Switching mental models between Vue and React timing hooks gets easier with guides like this on daily.dev._

## Community discussion

Top comments from developers on daily.dev.

**@allinonetools** · 1 upvotes

> The stale closure example is especially useful because it shows how React’s rendering model can catch Vue developers off guard. Comparing `useEffect` with Vue’s watchers side by side makes these differences much easier to understand in practice.

**@pdfopsdev** · 0 upvotes

> the stale closure thing trips up basically every vue dev moving to react at least once. vue's auto-tracking just hides the problem that useEffect's dep array forces you to confront head on.

## Similar posts on daily.dev

- [Stale Closures](https://daily.dev/posts/stale-closures-5okx3srky) · Medium · 1 upvotes · 0 comments
- [Vue Basics: Ultimate Guide to Vue 3 Reactivity](https://daily.dev/posts/vue-basics-ultimate-guide-to-vue-3-reactivity-l3lntlfjf) · Telerik · 52 upvotes · 1 comments
- [React for Vue Developers, 1: Components, Props, Mental Reset](https://daily.dev/posts/react-for-vue-developers-1-components-props-mental-reset-hvn1ca7um) · Telerik · 6 upvotes · 0 comments
- [React has changed, your Hooks should too](https://daily.dev/posts/react-has-changed-your-hooks-should-too-hokoxoemk) · Matt Smith · 38 upvotes · 5 comments
- [React and Vue Are Turning Into the Same Framework](https://daily.dev/posts/react-and-vue-are-turning-into-the-same-framework-gdlameyal) · DEV · 22 upvotes · 2 comments

---

Tags: [#javascript](https://daily.dev/tags/javascript), [#react](https://daily.dev/tags/react), [#vuejs](https://daily.dev/tags/vuejs)

[View this post on daily.dev](https://daily.dev/posts/react-for-vue-developers-2-state-effects-re-renders-lf4kx00ba)

```json
{"@context":"https://schema.org","@graph":[{"@type":"Organization","@id":"https://daily.dev/#organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180},"sameAs":["https://twitter.com/dailydotdev","https://github.com/dailydotdev","https://www.linkedin.com/company/daily-dev-ltd"]},{"@type":"WebSite","@id":"https://daily.dev/#website","url":"https://daily.dev","name":"daily.dev","publisher":{"@id":"https://daily.dev/#organization"},"potentialAction":{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https://daily.dev/search?q={search_term_string}"},"query-input":"required name=search_term_string"}}]}
{"@context":"https://schema.org","@type":"TechArticle","headline":"React for Vue Developers, 2: State, Effects, Re-renders","url":"https://daily.dev/posts/react-for-vue-developers-2-state-effects-re-renders-lf4kx00ba","mainEntityOfPage":{"@type":"WebPage","@id":"https://daily.dev/posts/react-for-vue-developers-2-state-effects-re-renders-lf4kx00ba"},"datePublished":"2026-10-01T18:00:01.595Z","dateModified":"2026-10-01T18:09:09.507Z","description":"This second installment of a series translating React concepts for Vue developers explains why React re-renders differently from Vue: React reruns the entire...","image":"https://media.daily.dev/image/upload/f_auto,q_auto/v1/posts/a8c13a865cf47c11d1503c46b6dc468f?_a=AQAEuop","thumbnailUrl":"https://media.daily.dev/image/upload/f_auto,q_auto/v1/posts/a8c13a865cf47c11d1503c46b6dc468f?_a=AQAEuop","isAccessibleForFree":true,"articleSection":"Telerik","inLanguage":"en","publisher":{"@type":"Organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180}},"author":{"@type":"Organization","name":"Telerik","logo":"https://media.daily.dev/image/upload/t_logo,f_auto/v1/logos/5ee6d4bef8ac4f84886d06f5881963e7","url":"https://daily.dev/sources/telerik"},"commentCount":2,"discussionUrl":"https://daily.dev/posts/react-for-vue-developers-2-state-effects-re-renders-lf4kx00ba","interactionStatistic":[{"@type":"InteractionCounter","interactionType":{"@type":"LikeAction"},"userInteractionCount":12},{"@type":"InteractionCounter","interactionType":{"@type":"CommentAction"},"userInteractionCount":2}],"keywords":"javascript,react,vuejs","timeRequired":"PT11M"}
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https://daily.dev"},{"@type":"ListItem","position":2,"name":"Telerik","item":"https://daily.dev/sources/telerik"},{"@type":"ListItem","position":3,"name":"React for Vue Developers, 2: State, Effects, Re-renders"}]}
{"@context":"https://schema.org","@type":"WebPage","@id":"https://daily.dev/posts/react-for-vue-developers-2-state-effects-re-renders-lf4kx00ba","comment":[{"@type":"Comment","text":"The stale closure example is especially useful because it shows how React’s rendering model can catch Vue developers off guard. Comparing useEffect with Vue’s watchers side by side makes these differences much easier to understand in practice.","datePublished":"2026-10-02T03:13:25.534Z","url":"https://daily.dev/posts/Lf4kX00bA#c-5nqM5AZbO","author":{"@type":"Person","name":"AllInOneTools","url":"https://daily.dev/allinonetools","image":"https://media.daily.dev/image/upload/s--4ZT8QlF0--/f_auto/v1769790028/avatars/avatar_igzBsWloJeaegzm9bQltZ?_a=BAMAMiiu0"},"interactionStatistic":{"@type":"InteractionCounter","interactionType":{"@type":"LikeAction"},"userInteractionCount":1}},{"@type":"Comment","text":"the stale closure thing trips up basically every vue dev moving to react at least once. vue’s auto-tracking just hides the problem that useEffect’s dep array forces you to confront head on.","datePublished":"2026-10-02T18:11:22.298Z","url":"https://daily.dev/posts/Lf4kX00bA#c-sa3jnHcsr","author":{"@type":"Person","name":"PDFops","url":"https://daily.dev/pdfopsdev","image":"https://media.daily.dev/image/upload/s---8isRBKc--/f_auto/v1782922291/avatars/avatar_orjMeK8QKaaVZwGq7ScPz?_a=BAMAMicg0"}}]}
{"@context":"https://schema.org","@type":"FAQPage","@id":"https://daily.dev/posts/react-for-vue-developers-2-state-effects-re-renders-lf4kx00ba#faq","mainEntity":[{"@type":"Question","name":"why does calling setCount twice in a row in React only increment the count by 1 instead of 2","acceptedAnswer":{"@type":"Answer","text":"Because the state variable is a constant snapshot captured for that specific render, so both calls read the same value, compute the same result, and overwrite each other. The fix is the functional updater form, such as setCount(c => c + 1), which receives the latest pending value instead of the stale render snapshot. This is the recommended approach whenever new state depends on previous state. Developers debugging stale state bugs in React can find clear before-and-after examples via daily.dev."}},{"@type":"Question","name":"why does my setInterval callback in a React useEffect keep using an old value of my state variable","acceptedAnswer":{"@type":"Answer","text":"This happens because the interval callback closes over the state variable's value from the render in which the effect ran, and that value never updates if the effect only runs once (empty dependency array). For example, a counter interval will increment once and then freeze, always computing 0 + 1. The fix is to use the functional updater form of the setter, which avoids reading the stale closed-over value entirely. When chasing stale closure bugs in React effects, daily.dev surfaces practical debugging explanations."}},{"@type":"Question","name":"what is the difference between useEffect and useLayoutEffect compared to Vue's onMounted","acceptedAnswer":{"@type":"Answer","text":"Vue's onMounted runs after the DOM is in place but before the browser paints, while React's useEffect runs after paint, making it invisible for tasks like fetching data or focusing an input. When layout must be measured or adjusted before the user sees it, useLayoutEffect is the closer match to onMounted's timing, since it also runs before paint. Switching mental models between Vue and React timing hooks gets easier with guides like this on daily.dev."}}]}
```

