<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>React函数组件更新 on Last Stand</title><link>https://amatsuzero.github.io/LastStand/tags/react%E5%87%BD%E6%95%B0%E7%BB%84%E4%BB%B6%E6%9B%B4%E6%96%B0/</link><description>Recent content in React函数组件更新 on Last Stand</description><generator>Hugo</generator><language>zh-cn</language><lastBuildDate>Wed, 16 Jul 2025 00:00:00 +0800</lastBuildDate><atom:link href="https://amatsuzero.github.io/LastStand/tags/react%E5%87%BD%E6%95%B0%E7%BB%84%E4%BB%B6%E6%9B%B4%E6%96%B0/index.xml" rel="self" type="application/rss+xml"/><item><title>React函数组件更新</title><link>https://amatsuzero.github.io/LastStand/posts/frontend/react/react-020/</link><pubDate>Tue, 17 Dec 2024 00:00:00 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/frontend/react/react-020/</guid><description>&lt;p&gt;React的函数组件（Function Components）自Hooks推出以来已成为React开发的主流方式。理解函数组件的更新原理对于编写高效、可维护的React应用至关重要。本文将深入探讨React函数组件的更新机制。&lt;/p&gt;
&lt;h2 id="一函数组件与类组件的本质区别"&gt;一、函数组件与类组件的本质区别&lt;/h2&gt;
&lt;p&gt;在深入更新原理前，我们需要明确函数组件与类组件的根本区别：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;类组件&lt;/strong&gt;：是类的实例，拥有实例属性和生命周期方法&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;函数组件&lt;/strong&gt;：是纯函数，接收props作为参数，返回JSX&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这种本质区别决定了它们的更新行为完全不同。&lt;/p&gt;
&lt;h2 id="二函数组件的执行机制"&gt;二、函数组件的执行机制&lt;/h2&gt;
&lt;p&gt;当React需要渲染一个函数组件时，它只是简单地&lt;strong&gt;调用这个函数&lt;/strong&gt;：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-jsx" data-lang="jsx"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;MyComponent&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;props&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;div&lt;/span&gt;&amp;gt;{&lt;span style="color:#a6e22e"&gt;props&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;message&lt;/span&gt;}&amp;lt;/&lt;span style="color:#f92672"&gt;div&lt;/span&gt;&amp;gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// React内部大致这样处理
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;element&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;MyComponent&lt;/span&gt;({ &lt;span style="color:#a6e22e"&gt;message&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;Hello&amp;#39;&lt;/span&gt; });
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;每次渲染都是&lt;strong&gt;全新的函数调用&lt;/strong&gt;，所有局部变量和函数都会重新创建。这与类组件形成鲜明对比，类组件在更新时会复用同一个实例。&lt;/p&gt;
&lt;h2 id="三触发更新的场景"&gt;三、触发更新的场景&lt;/h2&gt;
&lt;p&gt;函数组件的更新主要由以下情况触发：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;父组件重新渲染&lt;/strong&gt;：即使props未变化，父组件渲染也会导致子组件重新渲染&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;props发生变化&lt;/strong&gt;：当传入组件的props值改变时&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;状态更新&lt;/strong&gt;：通过useState、useReducer等Hook更新状态&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;context变化&lt;/strong&gt;：组件订阅的context值发生变化&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Hooks依赖变化&lt;/strong&gt;：useEffect、useMemo等Hook的依赖项发生变化&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="四react的渲染流程"&gt;四、React的渲染流程&lt;/h2&gt;
&lt;p&gt;函数组件的更新遵循React的渲染流程：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;触发更新&lt;/strong&gt;：通过setState、父组件渲染等途径触发更新&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;协调阶段（Reconciliation）&lt;/strong&gt;：&lt;br&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;React调用函数组件获取新的JSX&lt;/li&gt;
&lt;li&gt;与上一次渲染的JSX进行对比（Virtual DOM Diff）&lt;/li&gt;
&lt;/ul&gt;
&lt;ol start="3"&gt;
&lt;li&gt;&lt;strong&gt;提交阶段（Commit）&lt;/strong&gt;：&lt;br&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;将差异应用到真实DOM&lt;/li&gt;
&lt;li&gt;执行useLayoutEffect的回调&lt;/li&gt;
&lt;/ul&gt;
&lt;ol start="4"&gt;
&lt;li&gt;&lt;strong&gt;浏览器绘制&lt;/strong&gt;：浏览器重绘屏幕&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;副作用执行&lt;/strong&gt;：执行useEffect的回调&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="五hooks与组件更新"&gt;五、Hooks与组件更新&lt;/h2&gt;
&lt;p&gt;Hooks是函数组件能够拥有状态和生命周期的关键。理解Hooks的工作机制对理解组件更新至关重要。&lt;/p&gt;
&lt;h3 id="usestate的工作原理"&gt;useState的工作原理&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-jsx" data-lang="jsx"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; [&lt;span style="color:#a6e22e"&gt;count&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;setCount&lt;/span&gt;] &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;useState&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;React会在组件首次渲染时为每个useState调用分配一个&amp;quot;状态单元&amp;quot;&lt;/li&gt;
&lt;li&gt;后续更新时，React会按照Hooks的调用顺序来提供对应的状态值&lt;/li&gt;
&lt;li&gt;setCount调用会触发组件的重新渲染&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="useeffect与更新"&gt;useEffect与更新&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-jsx" data-lang="jsx"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;useEffect&lt;/span&gt;(() =&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 副作用代码
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; () =&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 清理函数
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; };
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}, [&lt;span style="color:#a6e22e"&gt;dependencies&lt;/span&gt;]);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;组件每次渲染后，React会比较依赖项数组&lt;/li&gt;
&lt;li&gt;如果依赖项变化或没有提供依赖项数组，副作用会重新执行&lt;/li&gt;
&lt;li&gt;清理函数会在副作用重新执行前或组件卸载时执行&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="六优化更新性能"&gt;六、优化更新性能&lt;/h2&gt;
&lt;p&gt;由于函数组件每次更新都会完整执行函数体，我们需要一些优化手段：&lt;/p&gt;</description></item></channel></rss>