{"id":5672,"date":"2025-04-28T16:54:15","date_gmt":"2025-04-28T21:54:15","guid":{"rendered":"https:\/\/frontendmasters.com\/blog\/?p=5672"},"modified":"2025-10-15T18:15:09","modified_gmt":"2025-10-15T23:15:09","slug":"react-internals-which-useeffect-runs-first","status":"publish","type":"post","link":"https:\/\/frontendmasters.com\/blog\/react-internals-which-useeffect-runs-first\/","title":{"rendered":"React Internals: Which useEffect runs first?"},"content":{"rendered":"\n<p><code><a href=\"https:\/\/react.dev\/reference\/react\/useEffect\">useEffect<\/a><\/code> is one of the most commonly used hooks in the React community. Regardless of how much experience you have with React, you\u2019ve probably used it before.<\/p>\n\n\n\n<p>But have you ever run into situations where <strong><code>useEffect<\/code> hooks run in an unexpected order<\/strong> when multiple layers of components are involved?<\/p>\n\n\n\n<p>Let\u2019s start with a quick quiz. <strong>What\u2019s the correct order of these <code>console.log<\/code> statements in the console?<\/strong><\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\"><span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">Parent<\/span>(<span class=\"hljs-params\">{ children }<\/span>) <\/span>{\n  <span class=\"hljs-built_in\">console<\/span>.log(<span class=\"hljs-string\">\"Parent is rendered\"<\/span>);\n  useEffect(<span class=\"hljs-function\"><span class=\"hljs-params\">()<\/span> =&gt;<\/span> {\n    <span class=\"hljs-built_in\">console<\/span>.log(<span class=\"hljs-string\">\"Parent committed effect\"<\/span>);\n  }, &#91;]);\n\n  <span class=\"hljs-keyword\">return<\/span> <span class=\"xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span>&gt;<\/span>{children}<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span><\/span>;\n}\n\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">Child<\/span>(<span class=\"hljs-params\"><\/span>) <\/span>{\n  <span class=\"hljs-built_in\">console<\/span>.log(<span class=\"hljs-string\">\"Child is rendered\"<\/span>);\n  useEffect(<span class=\"hljs-function\"><span class=\"hljs-params\">()<\/span> =&gt;<\/span> {\n    <span class=\"hljs-built_in\">console<\/span>.log(<span class=\"hljs-string\">\"Child committed effect\"<\/span>);\n  }, &#91;]);\n\n  <span class=\"hljs-keyword\">return<\/span> <span class=\"xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">p<\/span>&gt;<\/span>Child<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">p<\/span>&gt;<\/span><\/span>;\n}\n\n<span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">default<\/span> <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">App<\/span>(<span class=\"hljs-params\"><\/span>) <\/span>{\n  <span class=\"hljs-keyword\">return<\/span> (\n    <span class=\"xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">Parent<\/span>&gt;<\/span>\n      <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">Child<\/span> \/&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">Parent<\/span>&gt;<\/span><\/span>\n  );\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<details class=\"wp-block-details is-layout-flow wp-block-details-is-layout-flow\"><summary>Answer<\/summary>\n<pre class=\"wp-block-preformatted\">\/\/ initial render<br>Parent is rendered<br>Child is rendered<br><br>\/\/ useEffects<br>Child committed effect<br>Parent committed effect<\/pre>\n<\/details>\n\n\n\n<p>If you got it right\u2014nice job! If not, no worries\u2014most React devs get this wrong too. In fact, this isn\u2019t something that\u2019s clearly documented or explained on the official React website.<\/p>\n\n\n\n<p>Let\u2019s explore why children components are rendered last but their effects are committed first. We\u2019ll dive into how and when React renders components and commits effects (<code>useEffect<\/code>). We\u2019ll touch on a few React internal concepts like the <strong>React Fiber architecture<\/strong> and its <strong>traversal algorithm<\/strong>.<\/p>\n\n\n\n<p class=\"learn-more\">Frontend Masters offers lots of courses on React, like Complete Intro to React and <a href=\"https:\/\/frontendmasters.com\/courses\/intermediate-react-v5\/\">Intermediate React<\/a> by <a href=\"https:\/\/frontendmasters.com\/courses\/complete-react-v9\/?utm_source=boost&amp;utm_medium=blog&amp;utm_campaign=boost\">Brian Holt<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Overview of React Internals<\/h2>\n\n\n\n<p>According to <a href=\"https:\/\/react.dev\/learn\/render-and-commit\">React official documentation<\/a>, the entire React\u2019s component lifecycle can be roughly divided into 3 phases: <em><strong>Trigger \u2192 Render \u2192 Commit<\/strong><\/em><\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Triggering a render<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>The component\u2019s initial render, or state updates with <code>setState<\/code>.<\/li>\n\n\n\n<li>A state update is put in a queue and scheduled to be processed by the React Scheduler.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Rendering<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>React calls the component and works on the state update.<\/li>\n\n\n\n<li>React reconciles and marks it as \u201cdirty\u201d for commit phase.<\/li>\n\n\n\n<li>Create new DOM node internally.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Committing to the DOM<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Apply actual DOM manipulation.<\/li>\n\n\n\n<li>Runs effects (<code>useEffect<\/code>, <code>useLayoutEffect<\/code>).<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">React Fiber Tree<\/h2>\n\n\n\n<p>Before diving into the traversal algorithm, we need to understand the <strong>React Fiber<\/strong> architecture. I\u2019ll try to keep this introduction beginner-friendly.<\/p>\n\n\n\n<p>Internally, React uses a tree-like data structure called <strong>fiber tree<\/strong> to represent the component hierarchy and track updates.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large is-resized\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"887\" height=\"1024\" src=\"https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2025\/04\/Screenshot-2025-04-22-at-9.40.32%E2%80%AFAM.png?resize=887%2C1024&#038;ssl=1\" alt=\"\" class=\"wp-image-5685\" style=\"width:480px;height:auto\" srcset=\"https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2025\/04\/Screenshot-2025-04-22-at-9.40.32%E2%80%AFAM.png?resize=887%2C1024&amp;ssl=1 887w, https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2025\/04\/Screenshot-2025-04-22-at-9.40.32%E2%80%AFAM.png?resize=260%2C300&amp;ssl=1 260w, https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2025\/04\/Screenshot-2025-04-22-at-9.40.32%E2%80%AFAM.png?resize=768%2C887&amp;ssl=1 768w, https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2025\/04\/Screenshot-2025-04-22-at-9.40.32%E2%80%AFAM.png?w=1022&amp;ssl=1 1022w\" sizes=\"auto, (max-width: 887px) 100vw, 887px\" \/><\/figure>\n<\/div>\n\n\n<p>From the diagram above, we can tell that <strong>fiber tree is not exactly a one-to-one mapping of DOM tree<\/strong>. It includes <strong>additional information<\/strong> that help React manage rendering more efficiently.<\/p>\n\n\n\n<p>Each node in this tree is called a <strong>fiber node.<\/strong> There are different kinds of fiber nodes such as <code>HostComponent<\/code> which refers to a <strong>native DOM element<\/strong>, like <code>&lt;div&gt;<\/code> or <code>&lt;p&gt;<\/code> in the diagram. <code>FiberRootNode<\/code> is the root node and will point to a different <code>HostRoot<\/code> node during each new render.<\/p>\n\n\n\n<p>Every fiber node contains properties like <code>props<\/code>, <code>state<\/code>, and most importantly:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><code>child<\/code> \u2013 The child of the fiber.<\/li>\n\n\n\n<li><code>sibling<\/code> \u2013 The sibling of the fiber.<\/li>\n\n\n\n<li><code>return<\/code> \u2013 The return value of the fiber is the parent fiber.<\/li>\n<\/ol>\n\n\n\n<p>These information allows React to form a tree.<\/p>\n\n\n\n<p>Every time there is a state update, React will construct a new fiber tree and compare against the old tree internally.<\/p>\n\n\n\n<p class=\"learn-more\">If you\u2019re interested in the detail, please check out <a href=\"https:\/\/jser.dev\/series\/react-source-code-walkthrough\">JSer\u2019s blog<\/a> or his super cool project <a href=\"https:\/\/jser.pro\/ddir\/rie?reactVersion=18.3.1&amp;snippetKey=hq8jm2ylzb9u8eh468\">React Internal Explorer<\/a>!<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">How Fiber Tree Is Traversed<\/h2>\n\n\n\n<p>Generally, React reuses the same traversal algorithm in many use cases.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large is-resized\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"576\" src=\"https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2025\/04\/React-traverse.gif?resize=1024%2C576&#038;ssl=1\" alt=\"\" class=\"wp-image-5686\" style=\"width:512px;height:auto\" srcset=\"https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2025\/04\/React-traverse.gif?resize=1024%2C576&amp;ssl=1 1024w, https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2025\/04\/React-traverse.gif?resize=300%2C169&amp;ssl=1 300w, https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2025\/04\/React-traverse.gif?resize=768%2C432&amp;ssl=1 768w\" sizes=\"auto, (max-width: 1000px) 100vw, 1000px\" \/><\/figure>\n<\/div>\n\n\n<p>The animation above shows how React walks the fiber tree. Notice that <strong>each node is stepped twice<\/strong>. The rule is simple:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Traverse downwards.<\/li>\n\n\n\n<li>In each fiber node, React checks\n<ol class=\"wp-block-list\">\n<li>If there\u2019s a child, move to the child.<\/li>\n\n\n\n<li>If there\u2019s no child, step again the current node. Then,\n<ol class=\"wp-block-list\">\n<li>If there\u2019s a sibling, move to the sibling.<\/li>\n\n\n\n<li>If there\u2019s no sibling, move up to its parent.<\/li>\n<\/ol>\n<\/li>\n<\/ol>\n<\/li>\n<\/ol>\n\n\n\n<p>This traversal algorithm ensures each node is stepped twice.<\/p>\n\n\n\n<p>Now, let\u2019s revisit the quiz above.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Render Phase<\/h2>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large is-resized\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"576\" src=\"https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2025\/04\/Copy-of-React-traverse.gif?resize=1024%2C576&#038;ssl=1\" alt=\"\" class=\"wp-image-5688\" style=\"width:528px;height:auto\" srcset=\"https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2025\/04\/Copy-of-React-traverse.gif?resize=1024%2C576&amp;ssl=1 1024w, https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2025\/04\/Copy-of-React-traverse.gif?resize=300%2C169&amp;ssl=1 300w, https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2025\/04\/Copy-of-React-traverse.gif?resize=768%2C432&amp;ssl=1 768w\" sizes=\"auto, (max-width: 1000px) 100vw, 1000px\" \/><\/figure>\n<\/div>\n\n\n<p>React traverses the fiber tree and recursively performs <strong>two steps<\/strong> on each fiber node:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>In the first step<\/strong>, React calls the component \u2014 this is where <code>console.log<\/code> statement is executed. React reconciles and marks the fiber as &#8220;dirty&#8221; if state or props have changed, preparing it for the commit phase.<\/li>\n\n\n\n<li><strong>In the second step<\/strong>, React constructs the new DOM node.<\/li>\n<\/ul>\n\n\n\n<p class=\"learn-more\">In the React source code, the process is named <a href=\"https:\/\/github.com\/facebook\/react\/blob\/c44e4a250557e53b120e40db8b01fb5fd93f1e35\/packages\/react-reconciler\/src\/ReactFiberWorkLoop.js#L2484\"><code>workLoop<\/code><\/a>. The first step is <a href=\"https:\/\/github.com\/facebook\/react\/blob\/c44e4a250557e53b120e40db8b01fb5fd93f1e35\/packages\/react-reconciler\/src\/ReactFiberWorkLoop.js#L2811\"><code>beginWork()<\/code><\/a>. The second step is <a href=\"https:\/\/github.com\/facebook\/react\/blob\/c44e4a250557e53b120e40db8b01fb5fd93f1e35\/packages\/react-reconciler\/src\/ReactFiberWorkLoop.js#L2831\"><code>completeWork()<\/code><\/a>.<\/p>\n\n\n\n<p>At the end of Render phase, a new fiber tree with the updated DOM nodes is generated. At this point, <strong>nothing has been committed to the real DOM yet.<\/strong> The actual DOM mutations will happen in the Commit phase.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Commit Phase<\/h2>\n\n\n\n<p>The <strong>commit phase<\/strong> is where actual <strong>DOM mutations<\/strong> and <strong>effect flushing<\/strong> (<code>useEffect<\/code>) take place. The traversal pattern remains the same, but DOM mutations and effect flushing are handled in separate walks.<\/p>\n\n\n\n<p>In this section, we\u2019ll skip DOM mutations and focus on the effect flushing walk.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Committing effects<\/h3>\n\n\n\n<p>React uses the same traversal algorithm. However, instead of checking whether a node has a child, it checks whether it has a subtree \u2014 which makes sense, because only React components can contain <code>useEffect<\/code> hooks. A DOM node like <code>&lt;p&gt;<\/code> won&#8217;t contain any React hooks.<\/p>\n\n\n\n<p>Nothing happens in the first step, but in the second step, it commits effects.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large is-resized\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"576\" src=\"https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2025\/04\/Example-1-commit.gif?resize=1024%2C576&#038;ssl=1\" alt=\"\" class=\"wp-image-5689\" style=\"width:553px;height:auto\" srcset=\"https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2025\/04\/Example-1-commit.gif?resize=1024%2C576&amp;ssl=1 1024w, https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2025\/04\/Example-1-commit.gif?resize=300%2C169&amp;ssl=1 300w, https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2025\/04\/Example-1-commit.gif?resize=768%2C432&amp;ssl=1 768w\" sizes=\"auto, (max-width: 1000px) 100vw, 1000px\" \/><\/figure>\n<\/div>\n\n\n<p>This depth-first traversal explains why child effects are run before parent effects. This is the root cause.<\/p>\n\n\n\n<p class=\"learn-more\">In the React source code, the recursive function for committing effects is named <a href=\"https:\/\/github.com\/facebook\/react\/blob\/c44e4a250557e53b120e40db8b01fb5fd93f1e35\/packages\/react-reconciler\/src\/ReactFiberCommitWork.js#L3283\"><code>recursivelyTraversePassiveMountEffect<\/code><\/a>.<\/p>\n\n\n\n<p>Now let\u2019s check out another quiz example. The result should make more sense to you now.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\"><span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">Parent<\/span>(<span class=\"hljs-params\">{ children }<\/span>) <\/span>{\n  <span class=\"hljs-built_in\">console<\/span>.log(<span class=\"hljs-string\">\"Parent is rendered\"<\/span>);\n  useEffect(<span class=\"hljs-function\"><span class=\"hljs-params\">()<\/span> =&gt;<\/span> {\n    <span class=\"hljs-built_in\">console<\/span>.log(<span class=\"hljs-string\">\"Parent committed effect\"<\/span>);\n  }, &#91;]);\n\n  <span class=\"hljs-keyword\">return<\/span> <span class=\"xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span>&gt;<\/span>{children}<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span><\/span>;\n}\n\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">Child<\/span>(<span class=\"hljs-params\"><\/span>) <\/span>{\n  <span class=\"hljs-built_in\">console<\/span>.log(<span class=\"hljs-string\">\"Child is rendered\"<\/span>);\n  useEffect(<span class=\"hljs-function\"><span class=\"hljs-params\">()<\/span> =&gt;<\/span> {\n    <span class=\"hljs-built_in\">console<\/span>.log(<span class=\"hljs-string\">\"Child committed effect\"<\/span>);\n  }, &#91;]);\n\n  <span class=\"hljs-keyword\">return<\/span> <span class=\"xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">p<\/span>&gt;<\/span>Child<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">p<\/span>&gt;<\/span><\/span>;\n}\n\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">ParentSibling<\/span>(<span class=\"hljs-params\"><\/span>) <\/span>{\n  <span class=\"hljs-built_in\">console<\/span>.log(<span class=\"hljs-string\">\"ParentSibling is rendered\"<\/span>);\n  useEffect(<span class=\"hljs-function\"><span class=\"hljs-params\">()<\/span> =&gt;<\/span> {\n    <span class=\"hljs-built_in\">console<\/span>.log(<span class=\"hljs-string\">\"ParentSibling committed effect\"<\/span>);\n  }, &#91;]);\n\n  <span class=\"hljs-keyword\">return<\/span> <span class=\"xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">p<\/span>&gt;<\/span>Parent's Sibling<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">p<\/span>&gt;<\/span><\/span>;\n}\n\n<span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">default<\/span> <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">App<\/span>(<span class=\"hljs-params\"><\/span>) <\/span>{\n  <span class=\"hljs-keyword\">return<\/span> (\n    <span class=\"xml\"><span class=\"hljs-tag\">&lt;&gt;<\/span>\n      <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">Parent<\/span>&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">Child<\/span> \/&gt;<\/span>\n      <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">Parent<\/span>&gt;<\/span>\n      <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">ParentSibling<\/span> \/&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;\/&gt;<\/span><\/span>\n  );\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<details class=\"wp-block-details is-layout-flow wp-block-details-is-layout-flow\"><summary>Answer<\/summary>\n<pre class=\"wp-block-preformatted\">\/\/ Initial render<br>Parent is rendered<br>Child is rendered<br>ParentSibling is rendered<br><br>\/\/ useEffects<br>Child committed effect<br>Parent committed effect<br>ParentSibling committed effect<\/pre>\n<\/details>\n\n\n\n<p>During the commit phase:<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large is-resized\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"576\" src=\"https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2025\/04\/Example-2-commit-1.gif?resize=1024%2C576&#038;ssl=1\" alt=\"\" class=\"wp-image-5748\" style=\"width:599px;height:auto\" srcset=\"https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2025\/04\/Example-2-commit-1.gif?resize=1024%2C576&amp;ssl=1 1024w, https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2025\/04\/Example-2-commit-1.gif?resize=300%2C169&amp;ssl=1 300w, https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2025\/04\/Example-2-commit-1.gif?resize=768%2C432&amp;ssl=1 768w\" sizes=\"auto, (max-width: 1000px) 100vw, 1000px\" \/><\/figure>\n<\/div>\n\n\n<p>Now, it should be self-explanatory why <strong>child effects are flushed before their parents<\/strong> during the commit phase.<\/p>\n\n\n\n<p>Understanding how and when React commits <code>useEffect<\/code> hooks can help you avoid subtle bugs and unexpected behaviors\u2014especially when working with complex component structures.<\/p>\n\n\n\n<p>Welcome to React internals!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>It&#8217;s not particularly obvious, but a child&#8217;s useEffect will run before a parent&#8217;s will. Let&#8217;s look at why.<\/p>\n","protected":false},"author":35,"featured_media":5717,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"sig_custom_text":"","sig_image_type":"featured-image","sig_custom_image":0,"sig_is_disabled":false,"inline_featured_image":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[1],"tags":[3,62,330,329],"class_list":["post-5672","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-blog-post","tag-javascript","tag-react","tag-react-hooks","tag-useeffect"],"acf":[],"jetpack_featured_media_url":"https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2025\/04\/useEffect.jpg?fit=1140%2C676&ssl=1","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/posts\/5672","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/users\/35"}],"replies":[{"embeddable":true,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/comments?post=5672"}],"version-history":[{"count":14,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/posts\/5672\/revisions"}],"predecessor-version":[{"id":7429,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/posts\/5672\/revisions\/7429"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/media\/5717"}],"wp:attachment":[{"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/media?parent=5672"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/categories?post=5672"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/tags?post=5672"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}