mirror of
https://github.com/ZiuChen/ZiuChen.github.io.git
synced 2025-08-24 20:21:48 +08:00
282 lines
113 KiB
JavaScript
282 lines
113 KiB
JavaScript
import{_ as s,o as n,c as a,R as l}from"./chunks/framework.a304f0f7.js";const A=JSON.parse('{"title":"React Hooks","description":"","frontmatter":{},"headers":[],"relativePath":"note/React Hooks.md","lastUpdated":1682869658000}'),p={name:"note/React Hooks.md"},o=l(`<h1 id="react-hooks" tabindex="-1">React Hooks <a class="header-anchor" href="#react-hooks" aria-label="Permalink to "React Hooks""></a></h1><ul><li>认识和体验Hooks</li><li>State/Effect</li><li>Context/Reducer</li><li>Callback/Memo</li><li>Ref/LayoutEffect</li><li>自定义Hooks使用</li></ul><h2 id="认识react-hooks" tabindex="-1">认识React Hooks <a class="header-anchor" href="#认识react-hooks" aria-label="Permalink to "认识React Hooks""></a></h2><p>Hooks 是 React16.8 推出的新特性</p><p>在没有Hooks时,类组件能够完成的大部分工作,函数式组件都无法胜任:</p><ul><li>类组件可以定义并保存组件内部状态,并在状态发生改变时触发视图重新渲染 <ul><li>函数式组件不行,每次调用函数其中的变量都会被重新初始化,重新渲染时整个函数都重新执行</li></ul></li><li>类组件可以在其内部的生命周期回调中添加副作用 <ul><li>例如<code>componentDidMount</code>在类组件生命周期只会执行一次</li><li>函数式组件没有生命周期,如果在函数体内发起网络请求,那每次重新渲染都会发起请求</li></ul></li></ul><p>类组件存在的问题:</p><ul><li>复杂组件变得难以理解 <ul><li>业务代码相互耦合,类组件变得复杂</li><li>逻辑强耦合在一起难以拆分,强行拆分会导致过度设计,进一步增加代码复杂度</li></ul></li><li>class关键字的理解 <ul><li>初学React时class关键字理解存在困难</li><li>处理<code>this</code>的指向问题需要花费额外的心智负担</li></ul></li><li>组件状态复用 <ul><li>要复用组件需要借助高阶组件</li><li><code>redux</code> 中的 <code>connect</code> 或者 <code>react-router</code> 中的 <code>withRouter</code>,高阶组件的目的就是为了状态复</li><li>或通过Provider、Consumer来共享状态,但是Comsumer嵌套问题较严重</li></ul></li></ul><p>Hooks带来的优势:</p><ul><li>在不编写class的情况下使用state和其他React特性(如生命周期)</li><li>Hooks 允许我们在函数式组件中使用状态,并在状态发生改变时让视图重新渲染</li><li>同时,我们还可以在函数式组件中使用生命周期回调</li><li>更多的优点 ...</li></ul><h2 id="计数器案例对比" tabindex="-1">计数器案例对比 <a class="header-anchor" href="#计数器案例对比" aria-label="Permalink to "计数器案例对比""></a></h2><p>分别使用Hooks和类组件编写一个计数器:</p><div class="vp-code-group"><div class="tabs"><input type="radio" name="group-_XWOW" id="tab-rQHwGp3" checked="checked"><label for="tab-rQHwGp3">CounterClass.jsx</label><input type="radio" name="group-_XWOW" id="tab-kfvB853"><label for="tab-kfvB853">CounterFunctional.jsx</label></div><div class="blocks"><div class="language-tsx active line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">tsx</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#676E95;font-style:italic;">// CounterClass.jsx</span></span>
|
||
<span class="line"><span style="color:#89DDFF;font-style:italic;">import</span><span style="color:#A6ACCD;"> React</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">PureComponent</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">}</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;font-style:italic;">from</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">'</span><span style="color:#C3E88D;">react</span><span style="color:#89DDFF;">'</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#89DDFF;font-style:italic;">export</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;font-style:italic;">default</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">class</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">CounterClass</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">extends</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">PureComponent</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
|
||
<span class="line"><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">constructor</span><span style="color:#89DDFF;">()</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">super</span><span style="color:#F07178;">()</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#89DDFF;">this.</span><span style="color:#A6ACCD;">state</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">{</span></span>
|
||
<span class="line"><span style="color:#F07178;"> count</span><span style="color:#89DDFF;">:</span><span style="color:#F07178;"> </span><span style="color:#F78C6C;">0</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#89DDFF;">}</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#89DDFF;">}</span></span>
|
||
<span class="line"><span style="color:#A6ACCD;"> </span><span style="color:#F07178;">setCount</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;font-style:italic;">num</span><span style="color:#89DDFF;">)</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#89DDFF;">this.</span><span style="color:#82AAFF;">setState</span><span style="color:#F07178;">(</span><span style="color:#89DDFF;">{</span></span>
|
||
<span class="line"><span style="color:#F07178;"> count</span><span style="color:#89DDFF;">:</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">num</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#89DDFF;">}</span><span style="color:#F07178;">)</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#89DDFF;">}</span></span>
|
||
<span class="line"><span style="color:#A6ACCD;"> </span><span style="color:#F07178;">render</span><span style="color:#89DDFF;">()</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#C792EA;">const</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">{</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">count</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">}</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">this.</span><span style="color:#A6ACCD;">state</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#89DDFF;font-style:italic;">return</span><span style="color:#F07178;"> (</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#89DDFF;"><</span><span style="color:#F07178;">div</span><span style="color:#89DDFF;">></span></span>
|
||
<span class="line"><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;"><</span><span style="color:#F07178;">div</span><span style="color:#89DDFF;">></span><span style="color:#A6ACCD;">CounterClass</span><span style="color:#89DDFF;"></</span><span style="color:#F07178;">div</span><span style="color:#89DDFF;">></span></span>
|
||
<span class="line"><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;"><</span><span style="color:#F07178;">div</span><span style="color:#89DDFF;">>{</span><span style="color:#A6ACCD;">count</span><span style="color:#89DDFF;">}</</span><span style="color:#F07178;">div</span><span style="color:#89DDFF;">></span></span>
|
||
<span class="line"><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;"><</span><span style="color:#F07178;">button</span><span style="color:#89DDFF;"> </span><span style="color:#C792EA;">onClick</span><span style="color:#89DDFF;">={()</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">=></span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">this.</span><span style="color:#82AAFF;">setCount</span><span style="color:#A6ACCD;">(count </span><span style="color:#89DDFF;">+</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">1</span><span style="color:#A6ACCD;">)</span><span style="color:#89DDFF;">}></span><span style="color:#A6ACCD;">+1</span><span style="color:#89DDFF;"></</span><span style="color:#F07178;">button</span><span style="color:#89DDFF;">></span></span>
|
||
<span class="line"><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;"><</span><span style="color:#F07178;">button</span><span style="color:#89DDFF;"> </span><span style="color:#C792EA;">onClick</span><span style="color:#89DDFF;">={()</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">=></span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">this.</span><span style="color:#82AAFF;">setCount</span><span style="color:#A6ACCD;">(count </span><span style="color:#89DDFF;">-</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">1</span><span style="color:#A6ACCD;">)</span><span style="color:#89DDFF;">}></span><span style="color:#A6ACCD;">-1</span><span style="color:#89DDFF;"></</span><span style="color:#F07178;">button</span><span style="color:#89DDFF;">></span></span>
|
||
<span class="line"><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;"></</span><span style="color:#F07178;">div</span><span style="color:#89DDFF;">></span></span>
|
||
<span class="line"><span style="color:#F07178;"> )</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#89DDFF;">}</span></span>
|
||
<span class="line"><span style="color:#89DDFF;">}</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br></div></div><div class="language-tsx line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">tsx</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#676E95;font-style:italic;">// CounterFunctional.jsx</span></span>
|
||
<span class="line"><span style="color:#89DDFF;font-style:italic;">import</span><span style="color:#A6ACCD;"> React</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">useState</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">}</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;font-style:italic;">from</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">'</span><span style="color:#C3E88D;">react</span><span style="color:#89DDFF;">'</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#89DDFF;font-style:italic;">export</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;font-style:italic;">default</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">function</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">CounterFunctional</span><span style="color:#89DDFF;">()</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#C792EA;">const</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">[</span><span style="color:#A6ACCD;">count</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">setCount</span><span style="color:#89DDFF;">]</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#82AAFF;">useState</span><span style="color:#F07178;">(</span><span style="color:#F78C6C;">0</span><span style="color:#F07178;">)</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#89DDFF;font-style:italic;">return</span><span style="color:#F07178;"> (</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#89DDFF;"><</span><span style="color:#F07178;">div</span><span style="color:#89DDFF;">></span></span>
|
||
<span class="line"><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;"><</span><span style="color:#F07178;">div</span><span style="color:#89DDFF;">></span><span style="color:#A6ACCD;">CounterFunctional</span><span style="color:#89DDFF;"></</span><span style="color:#F07178;">div</span><span style="color:#89DDFF;">></span></span>
|
||
<span class="line"><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;"><</span><span style="color:#F07178;">div</span><span style="color:#89DDFF;">>{</span><span style="color:#A6ACCD;">count</span><span style="color:#89DDFF;">}</</span><span style="color:#F07178;">div</span><span style="color:#89DDFF;">></span></span>
|
||
<span class="line"><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;"><</span><span style="color:#F07178;">button</span><span style="color:#89DDFF;"> </span><span style="color:#C792EA;">onClick</span><span style="color:#89DDFF;">={()</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">=></span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">setCount</span><span style="color:#A6ACCD;">(count </span><span style="color:#89DDFF;">+</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">1</span><span style="color:#A6ACCD;">)</span><span style="color:#89DDFF;">}></span><span style="color:#A6ACCD;">+1</span><span style="color:#89DDFF;"></</span><span style="color:#F07178;">button</span><span style="color:#89DDFF;">></span></span>
|
||
<span class="line"><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;"><</span><span style="color:#F07178;">button</span><span style="color:#89DDFF;"> </span><span style="color:#C792EA;">onClick</span><span style="color:#89DDFF;">={()</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">=></span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">setCount</span><span style="color:#A6ACCD;">(count </span><span style="color:#89DDFF;">-</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">1</span><span style="color:#A6ACCD;">)</span><span style="color:#89DDFF;">}></span><span style="color:#A6ACCD;">-1</span><span style="color:#89DDFF;"></</span><span style="color:#F07178;">button</span><span style="color:#89DDFF;">></span></span>
|
||
<span class="line"><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;"></</span><span style="color:#F07178;">div</span><span style="color:#89DDFF;">></span></span>
|
||
<span class="line"><span style="color:#F07178;"> )</span></span>
|
||
<span class="line"><span style="color:#89DDFF;">}</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br></div></div></div></div><h3 id="解读usestate" tabindex="-1">解读useState <a class="header-anchor" href="#解读usestate" aria-label="Permalink to "解读useState""></a></h3><p>Hook本质上就是一个JavaScript函数,这个函数可以帮你钩入(Hook Into) React State以及其他的生命周期回调</p><ul><li><p>只允许在函数顶层调用Hook,而不能再循环、条件判断或子函数中调用</p></li><li><p>只能在React的函数组件中调用Hook,不能在其他JavaScript函数中调用</p></li><li><p>从<code>react</code>导入<code>useState</code></p><ul><li>参数 状态初始值 不设置则为<code>undefined</code></li><li>返回值是一个数组 <ul><li>0位元素 <strong>当前状态的值</strong>,当函数第一次调用时为初始值</li><li>1位元素 设置状态值的函数</li></ul></li><li>当点击button按钮后,会完成两件事情: <ul><li>调用<code>setCount</code>函数,将状态设置为新的值</li><li>触发组件重新渲染(函数重新执行),使用新的state值渲染DOM</li></ul></li></ul></li><li><p>为什么叫<code>useState</code>而不叫<code>createState</code>?</p><ul><li>create的含义不是很明确,因为state仅在组件首次渲染时被创建</li><li>在下一次重新渲染时,useState返回给我们当前的state</li><li>如果每次都创建新的变量,那它就不是state了</li><li>这也是Hook的名字总是以“use”开头的原因</li></ul></li></ul><h2 id="useeffect" tabindex="-1">useEffect <a class="header-anchor" href="#useeffect" aria-label="Permalink to "useEffect""></a></h2><p><code>useEffect</code>这个Hook可以帮我们处理一些副作用,<strong>每次组件渲染完成后</strong>,React会自动帮我们调用这些副作用</p><ul><li><p>网络请求/手动更新DOM/事件监听</p></li><li><p>完成上述这些功能的Hook被称为 Effect Hook</p></li><li><p>通过<code>useEffect</code>,可以告诉React需要在组件渲染完成后执行哪些副作用</p></li><li><p>这里的<em>组件重新渲染</em>,指的是组件对应的<strong>DOM更新完毕后</strong>,回调这些副作用函数</p></li><li><p>默认情况下,无论是第一次渲染之后,还是每次更新之后,都会执行这个副作用函数</p></li></ul><p>以下面的代码为例,我们希望每次对状态<code>title</code>进行修改后,都能反映到当前页面的标题上</p><p>如果我们将<code>document.title = title</code>放到函数顶层执行,那么</p><div class="language-tsx line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">tsx</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#676E95;font-style:italic;">// TitleChanger.jsx</span></span>
|
||
<span class="line"><span style="color:#89DDFF;font-style:italic;">import</span><span style="color:#A6ACCD;"> React</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">useEffect</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">useState</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">}</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;font-style:italic;">from</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">'</span><span style="color:#C3E88D;">react</span><span style="color:#89DDFF;">'</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#89DDFF;font-style:italic;">export</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;font-style:italic;">default</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">function</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">TitleChanger</span><span style="color:#89DDFF;">()</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#C792EA;">const</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">[</span><span style="color:#A6ACCD;">title</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">setTitle</span><span style="color:#89DDFF;">]</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#82AAFF;">useState</span><span style="color:#F07178;">(</span><span style="color:#89DDFF;">'</span><span style="color:#C3E88D;">Title</span><span style="color:#89DDFF;">'</span><span style="color:#F07178;">)</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#82AAFF;">useEffect</span><span style="color:#F07178;">(</span><span style="color:#89DDFF;">()</span><span style="color:#F07178;"> </span><span style="color:#C792EA;">=></span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">{</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">document</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">title</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">title</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#89DDFF;">}</span><span style="color:#F07178;">)</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#89DDFF;font-style:italic;">return</span><span style="color:#F07178;"> (</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#89DDFF;"><</span><span style="color:#F07178;">div</span><span style="color:#89DDFF;">></span></span>
|
||
<span class="line"><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;"><</span><span style="color:#F07178;">div</span><span style="color:#89DDFF;">></span><span style="color:#A6ACCD;">Title: </span><span style="color:#89DDFF;">{</span><span style="color:#A6ACCD;">title</span><span style="color:#89DDFF;">}</</span><span style="color:#F07178;">div</span><span style="color:#89DDFF;">></span></span>
|
||
<span class="line"><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;"><</span><span style="color:#F07178;">button</span><span style="color:#89DDFF;"> </span><span style="color:#C792EA;">onClick</span><span style="color:#89DDFF;">={()</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">=></span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">setTitle</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">new</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">Date</span><span style="color:#A6ACCD;">()</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">getTime</span><span style="color:#A6ACCD;">())</span><span style="color:#89DDFF;">}></span><span style="color:#A6ACCD;">Change Title</span><span style="color:#89DDFF;"></</span><span style="color:#F07178;">button</span><span style="color:#89DDFF;">></span></span>
|
||
<span class="line"><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;"></</span><span style="color:#F07178;">div</span><span style="color:#89DDFF;">></span></span>
|
||
<span class="line"><span style="color:#F07178;"> )</span></span>
|
||
<span class="line"><span style="color:#89DDFF;">}</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br></div></div><h3 id="清理副作用" tabindex="-1">清理副作用 <a class="header-anchor" href="#清理副作用" aria-label="Permalink to "清理副作用""></a></h3><p>使用useEffect可以帮我们在组件执行重新渲染后添加额外的副作用,那怎样清理这些副作用呢?</p><ul><li>例如,我们使用<code>useEffect</code>添加了事件监听回调的副作用</li><li>当组件被卸载时,需要对事件监听回调执行清理</li><li><code>addEventListener <=> removeEventListener</code></li></ul><p>传入useEffect的函数的返回值是一个函数,组件被重新渲染或组件被卸载时,React会调用这个函数</p><p>我们可以借助这个功能来完成清理副作用的操作</p><p>下面的案例展示了一个输入框,当焦点处于输入框时,按下ESC键时会对输入框进行清空并使其失焦:</p><div class="language-tsx line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">tsx</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#676E95;font-style:italic;">// KeydownListener.jsx</span></span>
|
||
<span class="line"><span style="color:#89DDFF;font-style:italic;">import</span><span style="color:#A6ACCD;"> React</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">useEffect</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">}</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;font-style:italic;">from</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">'</span><span style="color:#C3E88D;">react</span><span style="color:#89DDFF;">'</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#89DDFF;font-style:italic;">export</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;font-style:italic;">default</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">function</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">KeydownListener</span><span style="color:#89DDFF;">()</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#C792EA;">const</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">handleKeydown</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;font-style:italic;">e</span><span style="color:#89DDFF;">)</span><span style="color:#F07178;"> </span><span style="color:#C792EA;">=></span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">{</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#89DDFF;font-style:italic;">if</span><span style="color:#F07178;"> (</span><span style="color:#A6ACCD;">e</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">key</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">===</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">'</span><span style="color:#C3E88D;">Escape</span><span style="color:#89DDFF;">'</span><span style="color:#F07178;">) </span><span style="color:#89DDFF;">{</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">e</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">target</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">value</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">''</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">e</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">target</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">blur</span><span style="color:#F07178;">()</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">console</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">log</span><span style="color:#F07178;">(</span><span style="color:#89DDFF;">'</span><span style="color:#C3E88D;">Escape Pressed</span><span style="color:#89DDFF;">'</span><span style="color:#F07178;">)</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#89DDFF;">}</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#89DDFF;">}</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#82AAFF;">useEffect</span><span style="color:#F07178;">(</span><span style="color:#89DDFF;">()</span><span style="color:#F07178;"> </span><span style="color:#C792EA;">=></span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">{</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#C792EA;">const</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">input</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">document</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">querySelector</span><span style="color:#F07178;">(</span><span style="color:#89DDFF;">'</span><span style="color:#C3E88D;">input</span><span style="color:#89DDFF;">'</span><span style="color:#F07178;">)</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">input</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">addEventListener</span><span style="color:#F07178;">(</span><span style="color:#89DDFF;">'</span><span style="color:#C3E88D;">keydown</span><span style="color:#89DDFF;">'</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">handleKeydown</span><span style="color:#F07178;">)</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">console</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">log</span><span style="color:#F07178;">(</span><span style="color:#89DDFF;">'</span><span style="color:#C3E88D;">Effect Ran</span><span style="color:#89DDFF;">'</span><span style="color:#F07178;">)</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#89DDFF;font-style:italic;">return</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">()</span><span style="color:#F07178;"> </span><span style="color:#C792EA;">=></span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">{</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">input</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">removeEventListener</span><span style="color:#F07178;">(</span><span style="color:#89DDFF;">'</span><span style="color:#C3E88D;">keydown</span><span style="color:#89DDFF;">'</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">handleKeydown</span><span style="color:#F07178;">)</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">console</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">log</span><span style="color:#F07178;">(</span><span style="color:#89DDFF;">'</span><span style="color:#C3E88D;">Effect Cleaned Up</span><span style="color:#89DDFF;">'</span><span style="color:#F07178;">)</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#89DDFF;">}</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#89DDFF;">}</span><span style="color:#F07178;">)</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#89DDFF;font-style:italic;">return</span><span style="color:#F07178;"> (</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#89DDFF;"><</span><span style="color:#F07178;">div</span><span style="color:#89DDFF;">></span></span>
|
||
<span class="line"><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;"><</span><span style="color:#F07178;">div</span><span style="color:#89DDFF;">></span><span style="color:#A6ACCD;">document</span><span style="color:#89DDFF;"></</span><span style="color:#F07178;">div</span><span style="color:#89DDFF;">></span></span>
|
||
<span class="line"><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;"><</span><span style="color:#F07178;">input</span><span style="color:#89DDFF;"> </span><span style="color:#C792EA;">type</span><span style="color:#89DDFF;">=</span><span style="color:#89DDFF;">"</span><span style="color:#C3E88D;">text</span><span style="color:#89DDFF;">"</span><span style="color:#89DDFF;"> /></span></span>
|
||
<span class="line"><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;"></</span><span style="color:#F07178;">div</span><span style="color:#89DDFF;">></span></span>
|
||
<span class="line"><span style="color:#F07178;"> )</span></span>
|
||
<span class="line"><span style="color:#89DDFF;">}</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br></div></div><p>为什么要在effect中返回一个函数?</p><ul><li>这时effect可选的清除机制,每个effect都可以返回一个清除函数</li><li>如此可以将添加和移除订阅的逻辑放在一起</li><li>它们都属于effect的一部分</li></ul><p>如果我们有较为复杂的逻辑,我们也可以在同一个组件中使用多个useEffect,并分别在不同的回调函数中返回清理副作用函数</p><h3 id="effect性能优化" tabindex="-1">Effect性能优化 <a class="header-anchor" href="#effect性能优化" aria-label="Permalink to "Effect性能优化""></a></h3><p>同时,我们也会发现一些问题,尽管我们保证了监听回调是时刻唯一、不会冗余的</p><p>但是组件每次重新渲染都会:先删除原来事件监听回调,再添加新的监听回调,这造成了额外的性能浪费</p><p>我们可以对此进行额外的优化</p><ul><li><code>useEffect</code>实际上有两个参数 <ul><li>参数一:函数,组件重新渲染时执行的回调函数</li><li>参数二:数组,回调函数在那些state发生变化时,才重新执行</li></ul></li></ul><p>默认情况下,如果不传第二个参数,没有指定更新依赖项,则只要组件重新渲染,Effect都会重新执行</p><p>如果我们为第二个参数传递一个空数组,则证明:此Effect没有依赖state,仅在首次渲染时被回调</p><div class="language-tsx line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">tsx</span><pre class="shiki material-theme-palenight has-highlighted-lines"><code><span class="line"><span style="color:#676E95;font-style:italic;">// KeydownListener.jsx</span></span>
|
||
<span class="line"><span style="color:#89DDFF;">...</span></span>
|
||
<span class="line"><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">useEffect</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">()</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">=></span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#C792EA;">const</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">input</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">document</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">querySelector</span><span style="color:#F07178;">(</span><span style="color:#89DDFF;">'</span><span style="color:#C3E88D;">input</span><span style="color:#89DDFF;">'</span><span style="color:#F07178;">)</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">input</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">addEventListener</span><span style="color:#F07178;">(</span><span style="color:#89DDFF;">'</span><span style="color:#C3E88D;">keydown</span><span style="color:#89DDFF;">'</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">handleKeydown</span><span style="color:#F07178;">)</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">console</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">log</span><span style="color:#F07178;">(</span><span style="color:#89DDFF;">'</span><span style="color:#C3E88D;">Effect Ran</span><span style="color:#89DDFF;">'</span><span style="color:#F07178;">)</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#89DDFF;font-style:italic;">return</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">()</span><span style="color:#F07178;"> </span><span style="color:#C792EA;">=></span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">{</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">input</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">removeEventListener</span><span style="color:#F07178;">(</span><span style="color:#89DDFF;">'</span><span style="color:#C3E88D;">keydown</span><span style="color:#89DDFF;">'</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">handleKeydown</span><span style="color:#F07178;">)</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">console</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">log</span><span style="color:#F07178;">(</span><span style="color:#89DDFF;">'</span><span style="color:#C3E88D;">Effect Cleaned Up</span><span style="color:#89DDFF;">'</span><span style="color:#F07178;">)</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#89DDFF;">}</span></span>
|
||
<span class="line highlighted"><span style="color:#F07178;"> </span><span style="color:#89DDFF;">},</span><span style="color:#A6ACCD;"> [])</span></span>
|
||
<span class="line"><span style="color:#89DDFF;">...</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br></div></div><h2 id="usecontext" tabindex="-1">useContext <a class="header-anchor" href="#usecontext" aria-label="Permalink to "useContext""></a></h2><p>在之前的开发中,要在组件中使用共享的Context有两种方式</p><ul><li>类组件可以通过<code>ClassName.contextType = SomeContext</code>绑定上下文</li><li>在类的函数中通过<code>this.context.xxx</code>获取上下文中共享的状态</li><li>同时有多个Context时/函数式组件中,通过<code>SomeContext.Consumer</code>的方式共享上下文状态</li></ul><p>其中最大的问题就是:多个Context在同时使用时会引入大量的嵌套,而<code>useContext</code>可以帮我们解决这个问题</p><p>通过<code>useContext</code>可以直接获取到某个上下文中共享的状态变量</p><div class="vp-code-group"><div class="tabs"><input type="radio" name="group-ZaEsf" id="tab-L8-3Mp8" checked="checked"><label for="tab-L8-3Mp8">Profile.jsx</label><input type="radio" name="group-ZaEsf" id="tab-uEufNNQ"><label for="tab-uEufNNQ">index.js</label><input type="radio" name="group-ZaEsf" id="tab-yeN0oYa"><label for="tab-yeN0oYa">App.jsx</label></div><div class="blocks"><div class="language-tsx active line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">tsx</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#676E95;font-style:italic;">// Profile.jsx</span></span>
|
||
<span class="line"><span style="color:#89DDFF;font-style:italic;">import</span><span style="color:#A6ACCD;"> React</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">useContext</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">}</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;font-style:italic;">from</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">'</span><span style="color:#C3E88D;">react</span><span style="color:#89DDFF;">'</span></span>
|
||
<span class="line"><span style="color:#89DDFF;font-style:italic;">import</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">UserContext</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">ThemeContext</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">}</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;font-style:italic;">from</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">'</span><span style="color:#C3E88D;">../context</span><span style="color:#89DDFF;">'</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#89DDFF;font-style:italic;">export</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;font-style:italic;">default</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">function</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">Profile</span><span style="color:#89DDFF;">()</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#C792EA;">const</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">userContext</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#82AAFF;">useContext</span><span style="color:#F07178;">(</span><span style="color:#A6ACCD;">UserContext</span><span style="color:#F07178;">)</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#C792EA;">const</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">themeContext</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#82AAFF;">useContext</span><span style="color:#F07178;">(</span><span style="color:#A6ACCD;">ThemeContext</span><span style="color:#F07178;">)</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#89DDFF;font-style:italic;">return</span><span style="color:#F07178;"> (</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#89DDFF;"><</span><span style="color:#F07178;">div</span><span style="color:#89DDFF;">></span></span>
|
||
<span class="line"><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;"><</span><span style="color:#F07178;">div</span><span style="color:#89DDFF;">></span><span style="color:#A6ACCD;">Profile</span><span style="color:#89DDFF;"></</span><span style="color:#F07178;">div</span><span style="color:#89DDFF;">></span></span>
|
||
<span class="line"><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;"><</span><span style="color:#F07178;">div</span><span style="color:#89DDFF;">></span><span style="color:#A6ACCD;">userName: </span><span style="color:#89DDFF;">{</span><span style="color:#A6ACCD;">userContext</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">userName</span><span style="color:#89DDFF;">}</</span><span style="color:#F07178;">div</span><span style="color:#89DDFF;">></span></span>
|
||
<span class="line"><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;"><</span><span style="color:#F07178;">div</span><span style="color:#89DDFF;">></span><span style="color:#A6ACCD;">age: </span><span style="color:#89DDFF;">{</span><span style="color:#A6ACCD;">userContext</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">age</span><span style="color:#89DDFF;">}</</span><span style="color:#F07178;">div</span><span style="color:#89DDFF;">></span></span>
|
||
<span class="line"><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;"><</span><span style="color:#F07178;">div</span><span style="color:#89DDFF;">></span><span style="color:#A6ACCD;">theme: </span><span style="color:#89DDFF;">{</span><span style="color:#A6ACCD;">themeContext</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">theme</span><span style="color:#89DDFF;">}</</span><span style="color:#F07178;">div</span><span style="color:#89DDFF;">></span></span>
|
||
<span class="line"><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;"></</span><span style="color:#F07178;">div</span><span style="color:#89DDFF;">></span></span>
|
||
<span class="line"><span style="color:#F07178;"> )</span></span>
|
||
<span class="line"><span style="color:#89DDFF;">}</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br></div></div><div class="language-tsx line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">tsx</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#676E95;font-style:italic;">// context/index.js</span></span>
|
||
<span class="line"><span style="color:#89DDFF;font-style:italic;">import</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">createContext</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">}</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;font-style:italic;">from</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">'</span><span style="color:#C3E88D;">react</span><span style="color:#89DDFF;">'</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#89DDFF;font-style:italic;">export</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">const</span><span style="color:#A6ACCD;"> UserContext </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">createContext</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">{</span></span>
|
||
<span class="line"><span style="color:#A6ACCD;"> </span><span style="color:#F07178;">userName</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">''</span><span style="color:#89DDFF;">,</span></span>
|
||
<span class="line"><span style="color:#A6ACCD;"> </span><span style="color:#F07178;">userAge</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">0</span></span>
|
||
<span class="line"><span style="color:#89DDFF;">}</span><span style="color:#A6ACCD;">)</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#89DDFF;font-style:italic;">export</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">const</span><span style="color:#A6ACCD;"> ThemeContext </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">createContext</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">{</span></span>
|
||
<span class="line"><span style="color:#A6ACCD;"> </span><span style="color:#F07178;">theme</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">'</span><span style="color:#C3E88D;">light</span><span style="color:#89DDFF;">'</span></span>
|
||
<span class="line"><span style="color:#89DDFF;">}</span><span style="color:#A6ACCD;">)</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br></div></div><div class="language-tsx line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">tsx</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#676E95;font-style:italic;">// App.jsx</span></span>
|
||
<span class="line"><span style="color:#89DDFF;font-style:italic;">import</span><span style="color:#A6ACCD;"> React </span><span style="color:#89DDFF;font-style:italic;">from</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">'</span><span style="color:#C3E88D;">react</span><span style="color:#89DDFF;">'</span></span>
|
||
<span class="line"><span style="color:#89DDFF;font-style:italic;">import</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">UserContext</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">ThemeContext</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">}</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;font-style:italic;">from</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">'</span><span style="color:#C3E88D;">./context</span><span style="color:#89DDFF;">'</span></span>
|
||
<span class="line"><span style="color:#89DDFF;font-style:italic;">import</span><span style="color:#A6ACCD;"> Profile </span><span style="color:#89DDFF;font-style:italic;">from</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">'</span><span style="color:#C3E88D;">./components/Profile</span><span style="color:#89DDFF;">'</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#89DDFF;font-style:italic;">export</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;font-style:italic;">default</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">function</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">App</span><span style="color:#89DDFF;">()</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#89DDFF;font-style:italic;">return</span><span style="color:#F07178;"> (</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#89DDFF;"><</span><span style="color:#F07178;">div</span><span style="color:#89DDFF;">></span></span>
|
||
<span class="line"><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;"><</span><span style="color:#FFCB6B;">UserContext.Provider</span><span style="color:#89DDFF;"> </span><span style="color:#C792EA;">value</span><span style="color:#89DDFF;">={{</span><span style="color:#A6ACCD;"> </span><span style="color:#F07178;">userName</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">'</span><span style="color:#C3E88D;">Ziu</span><span style="color:#89DDFF;">'</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#F07178;">age</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">18</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">}}></span></span>
|
||
<span class="line"><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;"><</span><span style="color:#FFCB6B;">ThemeContext.Provider</span><span style="color:#89DDFF;"> </span><span style="color:#C792EA;">value</span><span style="color:#89DDFF;">={{</span><span style="color:#A6ACCD;"> </span><span style="color:#F07178;">theme</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">'</span><span style="color:#C3E88D;">dark</span><span style="color:#89DDFF;">'</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">}}></span></span>
|
||
<span class="line"><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;"><</span><span style="color:#FFCB6B;">Profile</span><span style="color:#89DDFF;"> /></span></span>
|
||
<span class="line"><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;"></</span><span style="color:#FFCB6B;">ThemeContext.Provider</span><span style="color:#89DDFF;">></span></span>
|
||
<span class="line"><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;"></</span><span style="color:#FFCB6B;">UserContext.Provider</span><span style="color:#89DDFF;">></span></span>
|
||
<span class="line"><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;"></</span><span style="color:#F07178;">div</span><span style="color:#89DDFF;">></span></span>
|
||
<span class="line"><span style="color:#F07178;"> )</span></span>
|
||
<span class="line"><span style="color:#89DDFF;">}</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br></div></div></div></div><p>当组件上层最近的<code>SomeContext.Provider</code>提供的值发生更新时,<code>useContext</code>会使用上下文中最新的数据触发组件的重新渲染</p><h2 id="usereducer" tabindex="-1">useReducer <a class="header-anchor" href="#usereducer" aria-label="Permalink to "useReducer""></a></h2><p><code>useReducer</code>并不是Redux的替代品</p><ul><li><code>useReducer</code>是<code>useState</code>在某些场景下的替代方案</li><li>如果state需要处理的<strong>数据较为复杂</strong>,我们可以通过<code>useReducer</code>对其进行拆分</li><li>或者需要修改的state需要依赖之前的state时,也可以使用<code>useReducer</code></li></ul><p>下面举一个例子:用户信息包含多个复杂的字段,当用户执行操作后需要同时对多个字段进行修改</p><p>我们分别用<code>useState</code>和<code>useReducer</code>来实现:</p><div class="vp-code-group"><div class="tabs"><input type="radio" name="group-iCdd_" id="tab-vce_vED" checked="checked"><label for="tab-vce_vED">UserInfoWithReducer.jsx</label><input type="radio" name="group-iCdd_" id="tab-bMS01HI"><label for="tab-bMS01HI">UserInfo.jsx</label></div><div class="blocks"><div class="language-tsx active line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">tsx</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#676E95;font-style:italic;">// UserInfoWithReducer.jsx</span></span>
|
||
<span class="line"><span style="color:#89DDFF;font-style:italic;">import</span><span style="color:#A6ACCD;"> React</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">useReducer</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">}</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;font-style:italic;">from</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">'</span><span style="color:#C3E88D;">react</span><span style="color:#89DDFF;">'</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#C792EA;">function</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">reducer</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;font-style:italic;">state</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#A6ACCD;font-style:italic;">action</span><span style="color:#89DDFF;">)</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#89DDFF;font-style:italic;">switch</span><span style="color:#F07178;"> (</span><span style="color:#A6ACCD;">action</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">type</span><span style="color:#F07178;">) </span><span style="color:#89DDFF;">{</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#89DDFF;font-style:italic;">case</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">'</span><span style="color:#C3E88D;">addAge</span><span style="color:#89DDFF;">'</span><span style="color:#89DDFF;">:</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#89DDFF;font-style:italic;">return</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">{</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#89DDFF;">...</span><span style="color:#A6ACCD;">state</span><span style="color:#89DDFF;">,</span></span>
|
||
<span class="line"><span style="color:#F07178;"> age</span><span style="color:#89DDFF;">:</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">state</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">age</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">+</span><span style="color:#F07178;"> </span><span style="color:#F78C6C;">1</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#89DDFF;">}</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#89DDFF;font-style:italic;">case</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">'</span><span style="color:#C3E88D;">pushLikes</span><span style="color:#89DDFF;">'</span><span style="color:#89DDFF;">:</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#89DDFF;font-style:italic;">return</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">{</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#89DDFF;">...</span><span style="color:#A6ACCD;">state</span><span style="color:#89DDFF;">,</span></span>
|
||
<span class="line"><span style="color:#F07178;"> likes</span><span style="color:#89DDFF;">:</span><span style="color:#F07178;"> [</span><span style="color:#89DDFF;">...</span><span style="color:#A6ACCD;">state</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">likes</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">action</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">payload</span><span style="color:#F07178;">]</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#89DDFF;">}</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#89DDFF;font-style:italic;">case</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">'</span><span style="color:#C3E88D;">modifyName</span><span style="color:#89DDFF;">'</span><span style="color:#89DDFF;">:</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#89DDFF;font-style:italic;">return</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">{</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#89DDFF;">...</span><span style="color:#A6ACCD;">state</span><span style="color:#89DDFF;">,</span></span>
|
||
<span class="line"><span style="color:#F07178;"> name</span><span style="color:#89DDFF;">:</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">action</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">payload</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#89DDFF;">}</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#89DDFF;font-style:italic;">default</span><span style="color:#89DDFF;">:</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#89DDFF;font-style:italic;">return</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">state</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#89DDFF;">}</span></span>
|
||
<span class="line"><span style="color:#89DDFF;">}</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#89DDFF;font-style:italic;">export</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;font-style:italic;">default</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">function</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">UserInfoWithReducer</span><span style="color:#89DDFF;">()</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#C792EA;">const</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">[</span><span style="color:#A6ACCD;">userInfo</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">dispatch</span><span style="color:#89DDFF;">]</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#82AAFF;">useReducer</span><span style="color:#F07178;">(</span><span style="color:#A6ACCD;">reducer</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">{</span></span>
|
||
<span class="line"><span style="color:#F07178;"> id</span><span style="color:#89DDFF;">:</span><span style="color:#F07178;"> </span><span style="color:#F78C6C;">1</span><span style="color:#89DDFF;">,</span></span>
|
||
<span class="line"><span style="color:#F07178;"> name</span><span style="color:#89DDFF;">:</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">'</span><span style="color:#C3E88D;">Ziu</span><span style="color:#89DDFF;">'</span><span style="color:#89DDFF;">,</span></span>
|
||
<span class="line"><span style="color:#F07178;"> age</span><span style="color:#89DDFF;">:</span><span style="color:#F07178;"> </span><span style="color:#F78C6C;">18</span><span style="color:#89DDFF;">,</span></span>
|
||
<span class="line"><span style="color:#F07178;"> likes</span><span style="color:#89DDFF;">:</span><span style="color:#F07178;"> [</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#89DDFF;">{</span><span style="color:#F07178;"> id</span><span style="color:#89DDFF;">:</span><span style="color:#F07178;"> </span><span style="color:#F78C6C;">5</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> name</span><span style="color:#89DDFF;">:</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">'</span><span style="color:#C3E88D;">Why</span><span style="color:#89DDFF;">'</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> age</span><span style="color:#89DDFF;">:</span><span style="color:#F07178;"> </span><span style="color:#F78C6C;">19</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">},</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#89DDFF;">{</span><span style="color:#F07178;"> id</span><span style="color:#89DDFF;">:</span><span style="color:#F07178;"> </span><span style="color:#F78C6C;">8</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> name</span><span style="color:#89DDFF;">:</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">'</span><span style="color:#C3E88D;">ZIU</span><span style="color:#89DDFF;">'</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> age</span><span style="color:#89DDFF;">:</span><span style="color:#F07178;"> </span><span style="color:#F78C6C;">20</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">}</span></span>
|
||
<span class="line"><span style="color:#F07178;"> ]</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#89DDFF;">}</span><span style="color:#F07178;">)</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#C792EA;">const</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">addAge</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">()</span><span style="color:#F07178;"> </span><span style="color:#C792EA;">=></span><span style="color:#F07178;"> </span><span style="color:#82AAFF;">dispatch</span><span style="color:#F07178;">(</span><span style="color:#89DDFF;">{</span><span style="color:#F07178;"> type</span><span style="color:#89DDFF;">:</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">'</span><span style="color:#C3E88D;">addAge</span><span style="color:#89DDFF;">'</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">}</span><span style="color:#F07178;">)</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#C792EA;">const</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">pushLikes</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;font-style:italic;">user</span><span style="color:#89DDFF;">)</span><span style="color:#F07178;"> </span><span style="color:#C792EA;">=></span><span style="color:#F07178;"> </span><span style="color:#82AAFF;">dispatch</span><span style="color:#F07178;">(</span><span style="color:#89DDFF;">{</span><span style="color:#F07178;"> type</span><span style="color:#89DDFF;">:</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">'</span><span style="color:#C3E88D;">pushLikes</span><span style="color:#89DDFF;">'</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> payload</span><span style="color:#89DDFF;">:</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">user</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">}</span><span style="color:#F07178;">)</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#C792EA;">const</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">modifyName</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;font-style:italic;">name</span><span style="color:#89DDFF;">)</span><span style="color:#F07178;"> </span><span style="color:#C792EA;">=></span><span style="color:#F07178;"> </span><span style="color:#82AAFF;">dispatch</span><span style="color:#F07178;">(</span><span style="color:#89DDFF;">{</span><span style="color:#F07178;"> type</span><span style="color:#89DDFF;">:</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">'</span><span style="color:#C3E88D;">modifyName</span><span style="color:#89DDFF;">'</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> payload</span><span style="color:#89DDFF;">:</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">name</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">}</span><span style="color:#F07178;">)</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#89DDFF;font-style:italic;">return</span><span style="color:#F07178;"> (</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#89DDFF;"><</span><span style="color:#F07178;">div</span><span style="color:#89DDFF;">></span></span>
|
||
<span class="line"><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;"><</span><span style="color:#F07178;">div</span><span style="color:#89DDFF;">></span><span style="color:#A6ACCD;">UserInfoWithReducer</span><span style="color:#89DDFF;"></</span><span style="color:#F07178;">div</span><span style="color:#89DDFF;">></span></span>
|
||
<span class="line"><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;"><</span><span style="color:#F07178;">div</span><span style="color:#89DDFF;">>{</span><span style="color:#A6ACCD;">JSON</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">stringify</span><span style="color:#A6ACCD;">(userInfo)</span><span style="color:#89DDFF;">}</</span><span style="color:#F07178;">div</span><span style="color:#89DDFF;">></span></span>
|
||
<span class="line"><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;"><</span><span style="color:#F07178;">button</span><span style="color:#89DDFF;"> </span><span style="color:#C792EA;">onClick</span><span style="color:#89DDFF;">={</span><span style="color:#A6ACCD;">addAge</span><span style="color:#89DDFF;">}></span><span style="color:#A6ACCD;">Add Age</span><span style="color:#89DDFF;"></</span><span style="color:#F07178;">button</span><span style="color:#89DDFF;">></span></span>
|
||
<span class="line"><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;"><</span><span style="color:#F07178;">button</span><span style="color:#89DDFF;"> </span><span style="color:#C792EA;">onClick</span><span style="color:#89DDFF;">={()</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">=></span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">pushLikes</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">{</span><span style="color:#A6ACCD;"> </span><span style="color:#F07178;">id</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">10</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#F07178;">name</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">'</span><span style="color:#C3E88D;">ZiuChen</span><span style="color:#89DDFF;">'</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#F07178;">age</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">21</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">}</span><span style="color:#A6ACCD;">)</span><span style="color:#89DDFF;">}></span><span style="color:#A6ACCD;">Push Likes</span><span style="color:#89DDFF;"></</span><span style="color:#F07178;">button</span><span style="color:#89DDFF;">></span></span>
|
||
<span class="line"><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;"><</span><span style="color:#F07178;">button</span><span style="color:#89DDFF;"> </span><span style="color:#C792EA;">onClick</span><span style="color:#89DDFF;">={()</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">=></span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">modifyName</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">'</span><span style="color:#C3E88D;">ZiuChen</span><span style="color:#89DDFF;">'</span><span style="color:#A6ACCD;">)</span><span style="color:#89DDFF;">}></span><span style="color:#A6ACCD;">Modify Name</span><span style="color:#89DDFF;"></</span><span style="color:#F07178;">button</span><span style="color:#89DDFF;">></span></span>
|
||
<span class="line"><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;"></</span><span style="color:#F07178;">div</span><span style="color:#89DDFF;">></span></span>
|
||
<span class="line"><span style="color:#F07178;"> )</span></span>
|
||
<span class="line"><span style="color:#89DDFF;">}</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br><span class="line-number">40</span><br><span class="line-number">41</span><br><span class="line-number">42</span><br><span class="line-number">43</span><br><span class="line-number">44</span><br><span class="line-number">45</span><br><span class="line-number">46</span><br><span class="line-number">47</span><br><span class="line-number">48</span><br><span class="line-number">49</span><br><span class="line-number">50</span><br></div></div><div class="language-tsx line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">tsx</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#676E95;font-style:italic;">// UserInfo.jsx</span></span>
|
||
<span class="line"><span style="color:#89DDFF;font-style:italic;">import</span><span style="color:#A6ACCD;"> React</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">useState</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">}</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;font-style:italic;">from</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">'</span><span style="color:#C3E88D;">react</span><span style="color:#89DDFF;">'</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#89DDFF;font-style:italic;">export</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;font-style:italic;">default</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">function</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">UserInfo</span><span style="color:#89DDFF;">()</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#C792EA;">const</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">[</span><span style="color:#A6ACCD;">userInfo</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">setUserInfo</span><span style="color:#89DDFF;">]</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#82AAFF;">useState</span><span style="color:#F07178;">(</span><span style="color:#89DDFF;">{</span></span>
|
||
<span class="line"><span style="color:#F07178;"> id</span><span style="color:#89DDFF;">:</span><span style="color:#F07178;"> </span><span style="color:#F78C6C;">1</span><span style="color:#89DDFF;">,</span></span>
|
||
<span class="line"><span style="color:#F07178;"> name</span><span style="color:#89DDFF;">:</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">'</span><span style="color:#C3E88D;">Ziu</span><span style="color:#89DDFF;">'</span><span style="color:#89DDFF;">,</span></span>
|
||
<span class="line"><span style="color:#F07178;"> age</span><span style="color:#89DDFF;">:</span><span style="color:#F07178;"> </span><span style="color:#F78C6C;">18</span><span style="color:#89DDFF;">,</span></span>
|
||
<span class="line"><span style="color:#F07178;"> likes</span><span style="color:#89DDFF;">:</span><span style="color:#F07178;"> [</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#89DDFF;">{</span><span style="color:#F07178;"> id</span><span style="color:#89DDFF;">:</span><span style="color:#F07178;"> </span><span style="color:#F78C6C;">5</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> name</span><span style="color:#89DDFF;">:</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">'</span><span style="color:#C3E88D;">Why</span><span style="color:#89DDFF;">'</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> age</span><span style="color:#89DDFF;">:</span><span style="color:#F07178;"> </span><span style="color:#F78C6C;">19</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">},</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#89DDFF;">{</span><span style="color:#F07178;"> id</span><span style="color:#89DDFF;">:</span><span style="color:#F07178;"> </span><span style="color:#F78C6C;">8</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> name</span><span style="color:#89DDFF;">:</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">'</span><span style="color:#C3E88D;">ZIU</span><span style="color:#89DDFF;">'</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> age</span><span style="color:#89DDFF;">:</span><span style="color:#F07178;"> </span><span style="color:#F78C6C;">20</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">}</span></span>
|
||
<span class="line"><span style="color:#F07178;"> ]</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#89DDFF;">}</span><span style="color:#F07178;">)</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#C792EA;">const</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">addAge</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">()</span><span style="color:#F07178;"> </span><span style="color:#C792EA;">=></span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#82AAFF;">setUserInfo</span><span style="color:#F07178;">(</span><span style="color:#89DDFF;">{</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#89DDFF;">...</span><span style="color:#A6ACCD;">userInfo</span><span style="color:#89DDFF;">,</span></span>
|
||
<span class="line"><span style="color:#F07178;"> age</span><span style="color:#89DDFF;">:</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">userInfo</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">age</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">+</span><span style="color:#F07178;"> </span><span style="color:#F78C6C;">1</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#89DDFF;">}</span><span style="color:#F07178;">)</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#C792EA;">const</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">pushLikes</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;font-style:italic;">user</span><span style="color:#89DDFF;">)</span><span style="color:#F07178;"> </span><span style="color:#C792EA;">=></span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#82AAFF;">setUserInfo</span><span style="color:#F07178;">(</span><span style="color:#89DDFF;">{</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#89DDFF;">...</span><span style="color:#A6ACCD;">userInfo</span><span style="color:#89DDFF;">,</span></span>
|
||
<span class="line"><span style="color:#F07178;"> likes</span><span style="color:#89DDFF;">:</span><span style="color:#F07178;"> [</span><span style="color:#89DDFF;">...</span><span style="color:#A6ACCD;">userInfo</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">likes</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">user</span><span style="color:#F07178;">]</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#89DDFF;">}</span><span style="color:#F07178;">)</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#C792EA;">const</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">modifyName</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;font-style:italic;">name</span><span style="color:#89DDFF;">)</span><span style="color:#F07178;"> </span><span style="color:#C792EA;">=></span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#82AAFF;">setUserInfo</span><span style="color:#F07178;">(</span><span style="color:#89DDFF;">{</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#89DDFF;">...</span><span style="color:#A6ACCD;">userInfo</span><span style="color:#89DDFF;">,</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">name</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#89DDFF;">}</span><span style="color:#F07178;">)</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#89DDFF;font-style:italic;">return</span><span style="color:#F07178;"> (</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#89DDFF;"><</span><span style="color:#F07178;">div</span><span style="color:#89DDFF;">></span></span>
|
||
<span class="line"><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;"><</span><span style="color:#F07178;">div</span><span style="color:#89DDFF;">></span><span style="color:#A6ACCD;">UserInfo</span><span style="color:#89DDFF;"></</span><span style="color:#F07178;">div</span><span style="color:#89DDFF;">></span></span>
|
||
<span class="line"><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;"><</span><span style="color:#F07178;">div</span><span style="color:#89DDFF;">>{</span><span style="color:#A6ACCD;">JSON</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">stringify</span><span style="color:#A6ACCD;">(userInfo)</span><span style="color:#89DDFF;">}</</span><span style="color:#F07178;">div</span><span style="color:#89DDFF;">></span></span>
|
||
<span class="line"><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;"><</span><span style="color:#F07178;">button</span><span style="color:#89DDFF;"> </span><span style="color:#C792EA;">onClick</span><span style="color:#89DDFF;">={()</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">=></span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">addAge</span><span style="color:#A6ACCD;">()</span><span style="color:#89DDFF;">}></span><span style="color:#A6ACCD;">Add Age</span><span style="color:#89DDFF;"></</span><span style="color:#F07178;">button</span><span style="color:#89DDFF;">></span></span>
|
||
<span class="line"><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;"><</span><span style="color:#F07178;">button</span><span style="color:#89DDFF;"> </span><span style="color:#C792EA;">onClick</span><span style="color:#89DDFF;">={()</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">=></span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">pushLikes</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">{</span><span style="color:#A6ACCD;"> </span><span style="color:#F07178;">id</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">10</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#F07178;">name</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">'</span><span style="color:#C3E88D;">ZiuChen</span><span style="color:#89DDFF;">'</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#F07178;">age</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">21</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">}</span><span style="color:#A6ACCD;">)</span><span style="color:#89DDFF;">}></span><span style="color:#A6ACCD;">Push Likes</span><span style="color:#89DDFF;"></</span><span style="color:#F07178;">button</span><span style="color:#89DDFF;">></span></span>
|
||
<span class="line"><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;"><</span><span style="color:#F07178;">button</span><span style="color:#89DDFF;"> </span><span style="color:#C792EA;">onClick</span><span style="color:#89DDFF;">={()</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">=></span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">modifyName</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">'</span><span style="color:#C3E88D;">ZiuChen</span><span style="color:#89DDFF;">'</span><span style="color:#A6ACCD;">)</span><span style="color:#89DDFF;">}></span><span style="color:#A6ACCD;">Modify Name</span><span style="color:#89DDFF;"></</span><span style="color:#F07178;">button</span><span style="color:#89DDFF;">></span></span>
|
||
<span class="line"><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;"></</span><span style="color:#F07178;">div</span><span style="color:#89DDFF;">></span></span>
|
||
<span class="line"><span style="color:#F07178;"> )</span></span>
|
||
<span class="line"><span style="color:#89DDFF;">}</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br><span class="line-number">40</span><br><span class="line-number">41</span><br><span class="line-number">42</span><br></div></div></div></div><p>从代码中可以看出差距:对于复杂的更新状态逻辑,使用<code>useReducer</code>可以将他们聚合在一起,通过统一的出口对状态进行更新,而不像<code>useState</code>方案中需要频繁调用暴露在外部的<code>setUserInfo</code>状态更新接口</p><p>当然,对于复杂数据的处理,也可以将其放到Redux这类的状态管理中,如果没有Redux,那么<code>useReducer</code>可以在一定程度上扮演Redux的角色,但是本质还是<code>useState</code>的替代方案</p><h2 id="usecallback和usememo" tabindex="-1">useCallback和useMemo <a class="header-anchor" href="#usecallback和usememo" aria-label="Permalink to "useCallback和useMemo""></a></h2><p>这两个Hook都是用于性能优化</p><h3 id="usecallback" tabindex="-1">useCallback <a class="header-anchor" href="#usecallback" aria-label="Permalink to "useCallback""></a></h3><p>我们以计数器案例来对<code>useCallback</code>进行说明:</p><div class="language-tsx line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">tsx</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#676E95;font-style:italic;">// Counter.jsx</span></span>
|
||
<span class="line"><span style="color:#89DDFF;font-style:italic;">import</span><span style="color:#A6ACCD;"> React</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">useState</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">}</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;font-style:italic;">from</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">'</span><span style="color:#C3E88D;">react</span><span style="color:#89DDFF;">'</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#89DDFF;font-style:italic;">export</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;font-style:italic;">default</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">function</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">Counter</span><span style="color:#89DDFF;">()</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#C792EA;">const</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">[</span><span style="color:#A6ACCD;">count</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">setCount</span><span style="color:#89DDFF;">]</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#82AAFF;">useState</span><span style="color:#F07178;">(</span><span style="color:#F78C6C;">0</span><span style="color:#F07178;">)</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#C792EA;">function</span><span style="color:#F07178;"> </span><span style="color:#82AAFF;">increment</span><span style="color:#89DDFF;">()</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">{</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#82AAFF;">setCount</span><span style="color:#F07178;">(</span><span style="color:#A6ACCD;">count</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">+</span><span style="color:#F07178;"> </span><span style="color:#F78C6C;">1</span><span style="color:#F07178;">)</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#89DDFF;">}</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#89DDFF;font-style:italic;">return</span><span style="color:#F07178;"> (</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#89DDFF;"><</span><span style="color:#F07178;">div</span><span style="color:#89DDFF;">></span></span>
|
||
<span class="line"><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;"><</span><span style="color:#F07178;">div</span><span style="color:#89DDFF;">></span><span style="color:#A6ACCD;">Counter</span><span style="color:#89DDFF;"></</span><span style="color:#F07178;">div</span><span style="color:#89DDFF;">></span></span>
|
||
<span class="line"><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;"><</span><span style="color:#F07178;">div</span><span style="color:#89DDFF;">>{</span><span style="color:#A6ACCD;">count</span><span style="color:#89DDFF;">}</</span><span style="color:#F07178;">div</span><span style="color:#89DDFF;">></span></span>
|
||
<span class="line"><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;"><</span><span style="color:#F07178;">button</span><span style="color:#89DDFF;"> </span><span style="color:#C792EA;">onClick</span><span style="color:#89DDFF;">={</span><span style="color:#A6ACCD;">increment</span><span style="color:#89DDFF;">}></span><span style="color:#A6ACCD;">+1</span><span style="color:#89DDFF;"></</span><span style="color:#F07178;">button</span><span style="color:#89DDFF;">></span></span>
|
||
<span class="line"><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;"></</span><span style="color:#F07178;">div</span><span style="color:#89DDFF;">></span></span>
|
||
<span class="line"><span style="color:#F07178;"> )</span></span>
|
||
<span class="line"><span style="color:#89DDFF;">}</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br></div></div><p>当我们每次点击<code>+1</code>的button时,整个函数都会被重新执行一次,但是<code>increment</code>也会被重复定义,虽然上一次组件渲染快照中的<code>increment</code>函数由于引用次数为0,会被GC机制回收,但是函数的重复定义对性能也存在消耗</p><p>但是<code>useCallback</code>的使用常常存在一个误区:使用<code>useCallback</code>可以减少函数重复定义,以此来进行性能优化</p><div class="language-tsx line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">tsx</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#676E95;font-style:italic;">// Counter.jsx</span></span>
|
||
<span class="line"><span style="color:#89DDFF;font-style:italic;">import</span><span style="color:#A6ACCD;"> React</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">useState</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">useCallback</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">}</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;font-style:italic;">from</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">'</span><span style="color:#C3E88D;">react</span><span style="color:#89DDFF;">'</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#89DDFF;font-style:italic;">export</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;font-style:italic;">default</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">function</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">Counter</span><span style="color:#89DDFF;">()</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#C792EA;">const</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">[</span><span style="color:#A6ACCD;">count</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">setCount</span><span style="color:#89DDFF;">]</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#82AAFF;">useState</span><span style="color:#F07178;">(</span><span style="color:#F78C6C;">0</span><span style="color:#F07178;">)</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#89DDFF;"> </span><span style="color:#676E95;font-style:italic;">// var1 = useCallback(fn1)</span></span>
|
||
<span class="line"><span style="color:#89DDFF;"> </span><span style="color:#676E95;font-style:italic;">// var2 = useCallback(fn2)</span></span>
|
||
<span class="line"><span style="color:#89DDFF;"> </span><span style="color:#676E95;font-style:italic;">// var1 === var2 === fn0</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#C792EA;">const</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">increment</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#82AAFF;">useCallback</span><span style="color:#F07178;">(</span><span style="color:#C792EA;">function</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">()</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">{</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#82AAFF;">setCount</span><span style="color:#F07178;">(</span><span style="color:#A6ACCD;">count</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">+</span><span style="color:#F07178;"> </span><span style="color:#F78C6C;">1</span><span style="color:#F07178;">)</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#89DDFF;">},</span><span style="color:#F07178;"> [</span><span style="color:#A6ACCD;">count</span><span style="color:#F07178;">])</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#89DDFF;font-style:italic;">return</span><span style="color:#F07178;"> (</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#89DDFF;"><</span><span style="color:#F07178;">div</span><span style="color:#89DDFF;">></span></span>
|
||
<span class="line"><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;"><</span><span style="color:#F07178;">div</span><span style="color:#89DDFF;">></span><span style="color:#A6ACCD;">Counter</span><span style="color:#89DDFF;"></</span><span style="color:#F07178;">div</span><span style="color:#89DDFF;">></span></span>
|
||
<span class="line"><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;"><</span><span style="color:#F07178;">div</span><span style="color:#89DDFF;">>{</span><span style="color:#A6ACCD;">count</span><span style="color:#89DDFF;">}</</span><span style="color:#F07178;">div</span><span style="color:#89DDFF;">></span></span>
|
||
<span class="line"><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;"><</span><span style="color:#F07178;">button</span><span style="color:#89DDFF;"> </span><span style="color:#C792EA;">onClick</span><span style="color:#89DDFF;">={</span><span style="color:#A6ACCD;">increment</span><span style="color:#89DDFF;">}></span><span style="color:#A6ACCD;">+1</span><span style="color:#89DDFF;"></</span><span style="color:#F07178;">button</span><span style="color:#89DDFF;">></span></span>
|
||
<span class="line"><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;"></</span><span style="color:#F07178;">div</span><span style="color:#89DDFF;">></span></span>
|
||
<span class="line"><span style="color:#F07178;"> )</span></span>
|
||
<span class="line"><span style="color:#89DDFF;">}</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br></div></div><p>本质上,传递给<code>useCallback</code>的参数时一个函数,这个函数在每次重新渲染时也会被重新定义,所以<code>useCallback</code>并没有解决函数重新定义的问题,它只是保证了组件每次访问<code>increment</code>时,访问到的都是同一个函数引用</p><ul><li><code>useCallback</code>会返回一个函数的memoized值</li><li>在依赖不变的情况下,多次定义时,返回的值是完全相同的</li></ul><p>在使用<code>useCallback</code>时,我们同样可以为其传入一个依赖数组,仅当依赖数组中的state值发生变化时,<code>useCallback</code>才会返回一个新的函数</p><p>当我们为其传入一个空的依赖数组时,这里涉及到一个概念:闭包陷阱</p><div class="language-tsx line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">tsx</span><pre class="shiki material-theme-palenight has-highlighted-lines"><code><span class="line"><span style="color:#676E95;font-style:italic;">// Counter.jsx</span></span>
|
||
<span class="line"><span style="color:#89DDFF;">...</span></span>
|
||
<span class="line"><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">const</span><span style="color:#A6ACCD;"> increment </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">useCallback</span><span style="color:#A6ACCD;">(</span><span style="color:#C792EA;">function</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">()</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#82AAFF;">setCount</span><span style="color:#F07178;">(</span><span style="color:#A6ACCD;">count</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">+</span><span style="color:#F07178;"> </span><span style="color:#F78C6C;">1</span><span style="color:#F07178;">)</span></span>
|
||
<span class="line highlighted"><span style="color:#F07178;"> </span><span style="color:#89DDFF;">},</span><span style="color:#A6ACCD;"> [])</span></span>
|
||
<span class="line"><span style="color:#89DDFF;">...</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br></div></div><p>即使我们多次点击+1的按钮,状态count也不会发生变化,这是因为依赖数组为空时,<code>useCallback</code>每次返回的都是第一次定义时的函数,而那个函数的<code>count</code>值始终为0,那么每次<code>setCount</code>得到的值都为1</p><blockquote><p>闭包陷阱:函数在定义时,从上层作用域捕获变量,并保存在闭包中。</p><p>后续即使重复定义新的函数,其取到的值仍然是闭包内部保存的变量的值,而这个值是始终没有发生改变的</p></blockquote><p>这里我们使用普通函数模拟了一下这个场景</p><div class="language-js line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#C792EA;">function</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">foo</span><span style="color:#89DDFF;">()</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#C792EA;">let</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">count</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#F78C6C;">0</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#C792EA;">function</span><span style="color:#F07178;"> </span><span style="color:#82AAFF;">bar</span><span style="color:#89DDFF;">()</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">{</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">console</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">log</span><span style="color:#F07178;">(</span><span style="color:#A6ACCD;">count</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">+</span><span style="color:#F07178;"> </span><span style="color:#F78C6C;">1</span><span style="color:#F07178;">)</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#89DDFF;">}</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#89DDFF;font-style:italic;">return</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">bar</span></span>
|
||
<span class="line"><span style="color:#89DDFF;">}</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#C792EA;">const</span><span style="color:#A6ACCD;"> bar1 </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">foo</span><span style="color:#A6ACCD;">()</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#82AAFF;">bar1</span><span style="color:#A6ACCD;">() </span><span style="color:#676E95;font-style:italic;">// 1</span></span>
|
||
<span class="line"><span style="color:#82AAFF;">bar1</span><span style="color:#A6ACCD;">() </span><span style="color:#676E95;font-style:italic;">// 1</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br></div></div><p>不论调用了多少次<code>bar1</code>,其内部取到的值都始终是最初的那个<code>count</code>,自然值也不会发生变化</p><p>所以,我们需要显式地为<code>useCallback</code>指定依赖state,这样才能让函数准确的使用到最新的状态</p><h3 id="真实的usecallback使用场景" tabindex="-1">真实的useCallback使用场景 <a class="header-anchor" href="#真实的usecallback使用场景" aria-label="Permalink to "真实的useCallback使用场景""></a></h3><p>经过之前的说明,目前<code>useCallback</code>看起来并没有实际的用途,它没有减少函数的定义次数,甚至在不合理使用时还会出现闭包陷阱,而带来的唯一好处就是:保证函数指向确定且唯一</p><p>下面我们举一个实际场景来说明<code>useCallback</code>的用途:</p>`,77),e=[o];function t(c,r,F,y,D,i){return n(),a("div",null,e)}const u=s(p,[["render",t]]);export{A as __pageData,u as default};
|