<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="4.2.2">Jekyll</generator><link href="https://kimserey.lam.gitlab.io/feed.xml" rel="self" type="application/atom+xml" /><link href="https://kimserey.lam.gitlab.io/" rel="alternate" type="text/html" /><updated>2026-03-28T11:01:04-05:00</updated><id>https://kimserey.lam.gitlab.io/feed.xml</id><title type="html">Kimserey Lam’s website, Software Development blog posts, videos and tutorials</title><subtitle>Kimserey Lam's website, Software Development Blog with tutorials and videos on backend, frontend and infrastructure.</subtitle><author><name>Kimserey Lam</name></author><entry><title type="html">Prevent Unnecessary Rendering When Using React Hooks</title><link href="https://kimserey.lam.gitlab.io/typescript/react/2022/07/15/prevent-unnecessary-rendering-when-using-react-hooks.html" rel="alternate" type="text/html" title="Prevent Unnecessary Rendering When Using React Hooks" /><published>2022-07-15T00:00:00-05:00</published><updated>2022-07-15T00:00:00-05:00</updated><id>https://kimserey.lam.gitlab.io/typescript/react/2022/07/15/prevent-unnecessary-rendering-when-using-react-hooks</id><content type="html" xml:base="https://kimserey.lam.gitlab.io/typescript/react/2022/07/15/prevent-unnecessary-rendering-when-using-react-hooks.html"><![CDATA[<p>When working with state hooks like <code class="language-plaintext highlighter-rouge">useReducer</code> or <code class="language-plaintext highlighter-rouge">useState</code> or <code class="language-plaintext highlighter-rouge">useContext</code>, it can become expensive to render components. If we let the framework handle rendering, all components and children components will be rendered if the parent uses state or context hooks or an action is dispatch into the reducer hook. Today we will look at optimisation to stop the rendering propagation for components which do not need to be rendered.</p>

<!--more-->

<ul>
  <li><a href="#localise-state">Localise State</a></li>
  <li><a href="#memo">Memo</a></li>
  <li><a href="#memo-with-change-function">Memo With Change Function</a></li>
</ul>

<h2 id="localise-state"><a href="#localise-state">Localise State</a></h2>

<p>The first technique is to organise state update to be localised into components that need updates. We can prevent rendering of all children elements by removing state change from the parent.</p>

<p>For example:</p>

<div class="language-ts highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
</pre></td><td class="rouge-code"><pre><span class="kd">const</span> <span class="nx">MyChildComp</span><span class="p">:</span> <span class="nx">FC</span><span class="o">&lt;</span><span class="p">{</span> <span class="na">toggled</span><span class="p">:</span> <span class="nx">boolean</span><span class="p">;</span> <span class="nl">onClick</span><span class="p">:</span> <span class="p">()</span> <span class="o">=&gt;</span> <span class="k">void</span> <span class="p">}</span><span class="o">&gt;</span> <span class="o">=</span> <span class="p">({</span>
  <span class="nx">toggled</span><span class="p">,</span>
  <span class="nx">onClick</span><span class="p">,</span>
<span class="p">})</span> <span class="o">=&gt;</span> <span class="p">{</span>
  <span class="k">return</span> <span class="p">(</span>
    <span class="o">&lt;&gt;</span>
      <span class="o">&lt;</span><span class="nx">div</span><span class="o">&gt;</span><span class="p">{</span><span class="nx">toggled</span> <span class="p">?</span> <span class="dl">"</span><span class="s2">hello</span><span class="dl">"</span> <span class="p">:</span> <span class="dl">"</span><span class="s2">bye</span><span class="dl">"</span><span class="p">}</span><span class="o">&lt;</span><span class="sr">/div</span><span class="err">&gt;
</span>      <span class="o">&lt;</span><span class="nx">button</span> <span class="nx">onClick</span><span class="o">=</span><span class="p">{()</span> <span class="o">=&gt;</span> <span class="nx">onClick</span><span class="p">()}</span><span class="o">&gt;</span><span class="nx">Click</span><span class="o">&lt;</span><span class="sr">/button</span><span class="err">&gt;
</span>    <span class="o">&lt;</span><span class="sr">/</span><span class="err">&gt;
</span>  <span class="p">);</span>
<span class="p">};</span>

<span class="kd">const</span> <span class="nx">MyParentComp</span><span class="p">:</span> <span class="nx">FC</span> <span class="o">=</span> <span class="p">()</span> <span class="o">=&gt;</span> <span class="p">{</span>
  <span class="kd">const</span> <span class="p">[</span><span class="nx">state</span><span class="p">,</span> <span class="nx">setState</span><span class="p">]</span> <span class="o">=</span> <span class="nx">useState</span><span class="p">(</span><span class="kc">true</span><span class="p">);</span>

  <span class="k">return</span> <span class="o">&lt;</span><span class="nx">MyChildComp</span> <span class="nx">toggled</span><span class="o">=</span><span class="p">{</span><span class="nx">state</span><span class="p">}</span> <span class="nx">onClick</span><span class="o">=</span><span class="p">{()</span> <span class="o">=&gt;</span> <span class="nx">setState</span><span class="p">(</span><span class="o">!</span><span class="nx">state</span><span class="p">)}</span> <span class="sr">/&gt;</span><span class="err">;
</span><span class="p">};</span>
</pre></td></tr></tbody></table></code></pre></div></div>

<p>If we have a state located in the parent component but is being used within the child component, any changes of the state will trigger a render of both components and any other children components of the parent component even if they don’t need the state.</p>

<p>Identifying such pattern can help in reducing rendering by moving the state closer to where it gets mutated, which mean in the example above, moving the state hook inside the child component rather than having it on the parent.</p>

<h2 id="memo"><a href="#memo">Memo</a></h2>

<p>But there are times where it is better to keep the state at the parent level and breakdown parts of the state to display in children components.</p>

<p>In that case any update will trigger a render of all components. To prevent that, we can use memo. This will make sure that the component is only rendered if the props have changed.</p>

<p>For example in a reducer hook:</p>

<div class="language-ts highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
</pre></td><td class="rouge-code"><pre><span class="kr">interface</span> <span class="nx">CounterState</span> <span class="p">{</span>
  <span class="nl">count</span><span class="p">:</span> <span class="kr">number</span><span class="p">;</span>
  <span class="nl">name</span><span class="p">:</span> <span class="kr">string</span><span class="p">;</span>
<span class="p">}</span>

<span class="kr">interface</span> <span class="nx">IncrementCounter</span> <span class="p">{</span>
  <span class="nl">kind</span><span class="p">:</span> <span class="dl">"</span><span class="s2">Increment</span><span class="dl">"</span><span class="p">;</span>
<span class="p">}</span>

<span class="kr">interface</span> <span class="nx">ChangeName</span> <span class="p">{</span>
  <span class="nl">kind</span><span class="p">:</span> <span class="dl">"</span><span class="s2">ChangeName</span><span class="dl">"</span><span class="p">;</span>
  <span class="nl">name</span><span class="p">:</span> <span class="kr">string</span><span class="p">;</span>
<span class="p">}</span>

<span class="kd">type</span> <span class="nx">CounterAction</span> <span class="o">=</span> <span class="nx">IncrementCounter</span> <span class="o">|</span> <span class="nx">ChangeName</span><span class="p">;</span>

<span class="kd">const</span> <span class="nx">reducer</span> <span class="o">=</span> <span class="p">(</span><span class="nx">state</span><span class="p">:</span> <span class="nx">CounterState</span><span class="p">,</span> <span class="nx">action</span><span class="p">:</span> <span class="nx">CounterAction</span><span class="p">):</span> <span class="nx">CounterState</span> <span class="o">=&gt;</span> <span class="p">{</span>
  <span class="k">switch</span> <span class="p">(</span><span class="nx">action</span><span class="p">.</span><span class="nx">kind</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">case</span> <span class="dl">"</span><span class="s2">Increment</span><span class="dl">"</span><span class="p">:</span>
      <span class="k">return</span> <span class="p">{</span> <span class="na">count</span><span class="p">:</span> <span class="nx">state</span><span class="p">.</span><span class="nx">count</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="na">name</span><span class="p">:</span> <span class="nx">state</span><span class="p">.</span><span class="nx">name</span> <span class="p">};</span>
    <span class="k">case</span> <span class="dl">"</span><span class="s2">ChangeName</span><span class="dl">"</span><span class="p">:</span>
      <span class="k">return</span> <span class="p">{</span> <span class="na">count</span><span class="p">:</span> <span class="nx">state</span><span class="p">.</span><span class="nx">count</span><span class="p">,</span> <span class="na">name</span><span class="p">:</span> <span class="nx">action</span><span class="p">.</span><span class="nx">name</span> <span class="p">};</span>
  <span class="p">}</span>
<span class="p">};</span>

<span class="kd">const</span> <span class="nx">DispatcherContext</span> <span class="o">=</span> <span class="nx">React</span><span class="p">.</span><span class="nx">createContext</span><span class="o">&lt;</span>
  <span class="p">{</span> <span class="na">dispatch</span><span class="p">:</span> <span class="nx">Dispatch</span><span class="o">&lt;</span><span class="nx">CounterAction</span><span class="o">&gt;</span> <span class="p">}</span> <span class="o">|</span> <span class="kc">undefined</span>
<span class="o">&gt;</span><span class="p">(</span><span class="kc">undefined</span><span class="p">);</span>

<span class="kd">const</span> <span class="nx">ButtonComponent</span><span class="p">:</span> <span class="nx">FC</span> <span class="o">=</span> <span class="p">()</span> <span class="o">=&gt;</span> <span class="p">{</span>
  <span class="kd">const</span> <span class="nx">dispatcher</span> <span class="o">=</span> <span class="nx">useContext</span><span class="p">(</span><span class="nx">DispatcherContext</span><span class="p">);</span>

  <span class="k">return</span> <span class="p">(</span>
    <span class="o">&lt;</span><span class="nx">div</span><span class="o">&gt;</span>
      <span class="o">&lt;</span><span class="nx">button</span> <span class="nx">onClick</span><span class="o">=</span><span class="p">{()</span> <span class="o">=&gt;</span> <span class="nx">dispatcher</span><span class="p">?.</span><span class="nx">dispatch</span><span class="p">({</span> <span class="na">kind</span><span class="p">:</span> <span class="dl">"</span><span class="s2">Increment</span><span class="dl">"</span> <span class="p">})}</span><span class="o">&gt;</span>
        <span class="nx">Increment</span>
      <span class="o">&lt;</span><span class="sr">/button</span><span class="err">&gt;
</span>      <span class="o">&lt;</span><span class="nx">button</span>
        <span class="nx">onClick</span><span class="o">=</span><span class="p">{()</span> <span class="o">=&gt;</span>
          <span class="nx">dispatcher</span><span class="p">?.</span><span class="nx">dispatch</span><span class="p">({</span> <span class="na">kind</span><span class="p">:</span> <span class="dl">"</span><span class="s2">ChangeName</span><span class="dl">"</span><span class="p">,</span> <span class="na">name</span><span class="p">:</span> <span class="dl">"</span><span class="s2">Hello </span><span class="dl">"</span> <span class="p">})</span>
        <span class="p">}</span>
      <span class="o">&gt;</span>
        <span class="nx">Change</span> <span class="nx">name</span>
      <span class="o">&lt;</span><span class="sr">/button</span><span class="err">&gt;
</span>    <span class="o">&lt;</span><span class="sr">/div</span><span class="err">&gt;
</span>  <span class="p">);</span>
<span class="p">};</span>

<span class="kd">const</span> <span class="nx">NameDisplay</span><span class="p">:</span> <span class="nx">FC</span><span class="o">&lt;</span><span class="p">{</span> <span class="na">name</span><span class="p">:</span> <span class="kr">string</span> <span class="p">}</span><span class="o">&gt;</span> <span class="o">=</span> <span class="p">({</span> <span class="nx">name</span> <span class="p">})</span> <span class="o">=&gt;</span> <span class="p">{</span>
  <span class="k">return</span> <span class="o">&lt;&gt;</span><span class="p">{</span><span class="nx">name</span><span class="p">}</span><span class="o">&lt;</span><span class="sr">/&gt;</span><span class="err">;
</span><span class="p">};</span>

<span class="kd">const</span> <span class="nx">App</span><span class="p">:</span> <span class="nx">FC</span> <span class="o">=</span> <span class="p">()</span> <span class="o">=&gt;</span> <span class="p">{</span>
  <span class="kd">const</span> <span class="nx">initialState</span> <span class="o">=</span> <span class="p">{</span>
    <span class="na">count</span><span class="p">:</span> <span class="mi">0</span><span class="p">,</span>
    <span class="na">name</span><span class="p">:</span> <span class="dl">""</span><span class="p">,</span>
  <span class="p">};</span>

  <span class="kd">const</span> <span class="p">[</span><span class="nx">state</span><span class="p">,</span> <span class="nx">dispatch</span><span class="p">]</span> <span class="o">=</span> <span class="nx">useReducer</span><span class="p">(</span><span class="nx">reducer</span><span class="p">,</span> <span class="nx">initialState</span><span class="p">);</span>

  <span class="k">return</span> <span class="p">(</span>
    <span class="o">&lt;</span><span class="nx">DispatcherContext</span><span class="p">.</span><span class="nx">Provider</span> <span class="nx">value</span><span class="o">=&gt;</span>
      <span class="o">&lt;</span><span class="nx">ButtonComponent</span><span class="o">&gt;&lt;</span><span class="sr">/ButtonComponent</span><span class="err">&gt;
</span>      <span class="o">&lt;</span><span class="nx">p</span><span class="o">&gt;</span><span class="p">{</span><span class="nx">state</span><span class="p">.</span><span class="nx">count</span><span class="p">}</span><span class="o">&lt;</span><span class="sr">/p</span><span class="err">&gt;
</span>      <span class="o">&lt;</span><span class="nx">NameDisplay</span> <span class="nx">name</span><span class="o">=</span><span class="p">{</span><span class="nx">state</span><span class="p">.</span><span class="nx">name</span><span class="p">}</span> <span class="sr">/</span><span class="err">&gt;
</span>    <span class="o">&lt;</span><span class="sr">/DispatcherContext.Provider</span><span class="err">&gt;
</span>  <span class="p">);</span>
<span class="p">};</span>
</pre></td></tr></tbody></table></code></pre></div></div>

<p>We have a reducer which keeps track of a counter with name and we have <code class="language-plaintext highlighter-rouge">NameDisplay</code>, a component which should render only if the <code class="language-plaintext highlighter-rouge">state.name</code> has changed. Currently any change on the state will trigger a render. To prevent that, we can use <code class="language-plaintext highlighter-rouge">memo</code>.</p>

<div class="language-ts highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
</pre></td><td class="rouge-code"><pre><span class="kd">const</span> <span class="nx">NameDisplay</span><span class="p">:</span> <span class="nx">FC</span><span class="o">&lt;</span><span class="p">{</span> <span class="na">name</span><span class="p">:</span> <span class="kr">string</span> <span class="p">}</span><span class="o">&gt;</span> <span class="o">=</span> <span class="nx">memo</span><span class="p">(({</span> <span class="nx">name</span> <span class="p">})</span> <span class="o">=&gt;</span> <span class="p">{</span>
  <span class="k">return</span> <span class="o">&lt;&gt;</span><span class="p">{</span><span class="nx">name</span><span class="p">}</span><span class="o">&lt;</span><span class="sr">/&gt;</span><span class="err">;
</span><span class="p">});</span>
</pre></td></tr></tbody></table></code></pre></div></div>

<h2 id="memo-with-change-function"><a href="#memo-with-change-function">Memo With Change Function</a></h2>

<p>Lastly when managing a large state object with reducer, it is sometime easier to pass as prop the whole state. For example instead of passing just the name, we pass the whole state:</p>

<div class="language-ts highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
</pre></td><td class="rouge-code"><pre><span class="kd">const</span> <span class="nx">NameDisplay</span><span class="p">:</span> <span class="nx">FC</span><span class="o">&lt;</span><span class="p">{</span> <span class="na">state</span><span class="p">:</span> <span class="nx">CounterState</span> <span class="p">}</span><span class="o">&gt;</span> <span class="o">=</span> <span class="nx">memo</span><span class="p">(({</span> <span class="nx">state</span> <span class="p">})</span> <span class="o">=&gt;</span> <span class="p">{</span>
  <span class="k">return</span> <span class="o">&lt;&gt;</span><span class="p">{</span><span class="nx">state</span><span class="p">.</span><span class="nx">name</span><span class="p">}</span><span class="o">&lt;</span><span class="sr">/&gt;</span><span class="err">;
</span><span class="p">});</span>
</pre></td></tr></tbody></table></code></pre></div></div>

<p>If we forward the whole state as prop, even when using memo, the components will still render.</p>

<p>To prevent this, we can use the equality argument from usememo to identify the part of the state that the component cares about and which would trigger rendering.</p>

<div class="language-ts highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
</pre></td><td class="rouge-code"><pre><span class="kd">const</span> <span class="nx">NameDisplay</span><span class="p">:</span> <span class="nx">FC</span><span class="o">&lt;</span><span class="p">{</span> <span class="na">state</span><span class="p">:</span> <span class="nx">CounterState</span> <span class="p">}</span><span class="o">&gt;</span> <span class="o">=</span> <span class="nx">memo</span><span class="p">(</span>
  <span class="p">({</span> <span class="nx">state</span> <span class="p">})</span> <span class="o">=&gt;</span> <span class="p">{</span>
    <span class="k">return</span> <span class="o">&lt;&gt;</span><span class="p">{</span><span class="nx">state</span><span class="p">.</span><span class="nx">name</span><span class="p">}</span><span class="o">&lt;</span><span class="sr">/&gt;</span><span class="err">;
</span>  <span class="p">},</span>
  <span class="p">(</span><span class="nx">cur</span><span class="p">,</span> <span class="nx">next</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="nx">cur</span><span class="p">.</span><span class="nx">state</span><span class="p">.</span><span class="nx">name</span> <span class="o">===</span> <span class="nx">next</span><span class="p">.</span><span class="nx">state</span><span class="p">.</span><span class="nx">name</span>
<span class="p">);</span>
</pre></td></tr></tbody></table></code></pre></div></div>

<p>And that concludes today’s post!</p>

<h2 id="conclusion">Conclusion</h2>

<p>Today we saw how we could optimise our components to avoid unnecessary rendering. We first saw that by simply reorganising the state, we can remove the need to render certain component. We then saw that by use memo we were able to make the component only render on prop change and lastly if not all values from an object give in prop is needed, we saw that we could use the equality argument to target the exact properties from the prop object. I hope you liked this post and I’ll see you on the next one!</p>]]></content><author><name>kimserey</name></author><category term="typescript" /><category term="react" /><summary type="html"><![CDATA[When working with state hooks like useReducer or useState or useContext, it can become expensive to render components. If we let the framework handle rendering, all components and children components will be rendered if the parent uses state or context hooks or an action is dispatch into the reducer hook. Today we will look at optimisation to stop the rendering propagation for components which do not need to be rendered.]]></summary></entry><entry><title type="html">Apollo Client Fetch Policy</title><link href="https://kimserey.lam.gitlab.io/typescript/graphql/react/2022/05/06/apollo-client-fetch-policy.html" rel="alternate" type="text/html" title="Apollo Client Fetch Policy" /><published>2022-05-06T00:00:00-05:00</published><updated>2022-05-06T00:00:00-05:00</updated><id>https://kimserey.lam.gitlab.io/typescript/graphql/react/2022/05/06/apollo-client-fetch-policy</id><content type="html" xml:base="https://kimserey.lam.gitlab.io/typescript/graphql/react/2022/05/06/apollo-client-fetch-policy.html"><![CDATA[<p>Last week we looked at Apollo Client and how it could be used to manage queries to GraphQL server. In today’s post, we’ll look at the different fetching policies provided to manage query data and caching.</p>

<!--more-->

<ul>
  <li><a href="#apollo-client-cache">Apollo Client Cache</a></li>
  <li><a href="#fetch-policy">Fetch Policy</a></li>
</ul>

<h2 id="apollo-client-cache"><a href="#apollo-client-cache">Apollo Client Cache</a></h2>

<p>Apollo Client manages a cache for us behind the scene to optimise performance. The data queried are normalized and stored in memory when the same data our queried.</p>

<p>To visualise the cache, we can get the Apollo Client chrome extension and open the developer took to see the cache section.</p>

<p><img src="/assets/posts/2022-05-06-apollo-fetch/apollo_client_cache.png" alt="picture" /></p>

<h2 id="fetch-policy"><a href="#fetch-policy">Fetch Policy</a></h2>

<p>To modify the fetch policy, we can specify it in the options of <code class="language-plaintext highlighter-rouge">useQuery</code>:</p>

<div class="language-ts highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
</pre></td><td class="rouge-code"><pre><span class="kd">const</span> <span class="p">{</span> <span class="nx">loading</span><span class="p">,</span> <span class="nx">error</span><span class="p">,</span> <span class="nx">data</span> <span class="p">}</span> <span class="o">=</span> <span class="nx">useQuery</span><span class="o">&lt;</span><span class="p">{</span>
  <span class="na">books</span><span class="p">:</span> <span class="p">{</span> <span class="na">title</span><span class="p">:</span> <span class="kr">string</span><span class="p">;</span> <span class="nl">author</span><span class="p">:</span> <span class="p">{</span> <span class="na">id</span><span class="p">:</span> <span class="kr">string</span><span class="p">;</span> <span class="nl">name</span><span class="p">:</span> <span class="kr">string</span> <span class="p">}</span> <span class="p">}[];</span>
<span class="p">}</span><span class="o">&gt;</span><span class="p">(</span><span class="nx">BOOKS</span><span class="p">,</span> <span class="p">{</span> <span class="na">variables</span><span class="p">:</span> <span class="p">{</span> <span class="na">bookId</span><span class="p">:</span> <span class="nx">id</span> <span class="p">},</span> <span class="na">fetchPolicy</span><span class="p">:</span> <span class="dl">"</span><span class="s2">cache-and-network</span><span class="dl">"</span> <span class="p">});</span>
</pre></td></tr></tbody></table></code></pre></div></div>

<p>For example here we’ve specified <code class="language-plaintext highlighter-rouge">cache-and-network</code>. There are a number of options available to manage the cache:</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">cache-first</code> hits the cache then if not present hit the server</li>
  <li><code class="language-plaintext highlighter-rouge">cache-only</code> only looks at the cache</li>
  <li><code class="language-plaintext highlighter-rouge">network-only</code> always consult the server but saves the result in cache</li>
  <li><code class="language-plaintext highlighter-rouge">cache-and-network</code> check in cache while also consulting server, and replace with server data if changed</li>
  <li><code class="language-plaintext highlighter-rouge">no-cache</code> consults the server and does not cache</li>
  <li><code class="language-plaintext highlighter-rouge">standby</code> same as cache-first except the query does not update the value</li>
</ul>

<p><code class="language-plaintext highlighter-rouge">cache-first</code> is the default behaviour, to use any other one, we must overwrite it.</p>

<p>Here is a working example to test the fetch policies.</p>

<p>We have a server with a query accepting a book ID.</p>

<div class="language-ts highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
</pre></td><td class="rouge-code"><pre><span class="k">import</span> <span class="p">{</span> <span class="nx">ApolloServer</span><span class="p">,</span> <span class="nx">gql</span> <span class="p">}</span> <span class="k">from</span> <span class="dl">"</span><span class="s2">apollo-server</span><span class="dl">"</span><span class="p">;</span>

<span class="kd">const</span> <span class="nx">typeDefs</span> <span class="o">=</span> <span class="nx">gql</span><span class="s2">`
  type Person {
    id: ID!
    name: String!
  }

  type Book {
    id: ID!
    title: String!
    author: Person!
  }

  type Query {
    books(id: ID): [Book]
  }
`</span><span class="p">;</span>

<span class="kd">const</span> <span class="nx">resolvers</span> <span class="o">=</span> <span class="p">{</span>
  <span class="na">Query</span><span class="p">:</span> <span class="p">{</span>
    <span class="na">books</span><span class="p">:</span> <span class="p">(</span><span class="na">_</span><span class="p">:</span> <span class="kr">any</span><span class="p">,</span> <span class="na">args</span><span class="p">:</span> <span class="kr">any</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
      <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="k">new</span> <span class="nb">Date</span><span class="p">().</span><span class="nx">toISOString</span><span class="p">(),</span> <span class="nx">args</span><span class="p">.</span><span class="nx">id</span><span class="p">);</span>
      <span class="k">return</span> <span class="p">[</span>
        <span class="p">{</span>
          <span class="na">id</span><span class="p">:</span> <span class="dl">"</span><span class="s2">1</span><span class="dl">"</span><span class="p">,</span>
          <span class="na">title</span><span class="p">:</span> <span class="dl">"</span><span class="s2">Made of Wolves</span><span class="dl">"</span><span class="p">,</span>
          <span class="na">authorId</span><span class="p">:</span> <span class="dl">"</span><span class="s2">1</span><span class="dl">"</span><span class="p">,</span>
        <span class="p">},</span>
        <span class="p">{</span>
          <span class="na">id</span><span class="p">:</span> <span class="dl">"</span><span class="s2">2</span><span class="dl">"</span><span class="p">,</span>
          <span class="na">title</span><span class="p">:</span> <span class="dl">"</span><span class="s2">The Visitor in the City</span><span class="dl">"</span><span class="p">,</span>
          <span class="na">authorId</span><span class="p">:</span> <span class="dl">"</span><span class="s2">2</span><span class="dl">"</span><span class="p">,</span>
        <span class="p">},</span>
      <span class="p">].</span><span class="nx">filter</span><span class="p">((</span><span class="nx">b</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="o">!</span><span class="nx">args</span><span class="p">.</span><span class="nx">id</span> <span class="o">||</span> <span class="nx">b</span><span class="p">.</span><span class="nx">id</span> <span class="o">===</span> <span class="nx">args</span><span class="p">.</span><span class="nx">id</span><span class="p">);</span>
    <span class="p">},</span>
  <span class="p">},</span>
  <span class="na">Book</span><span class="p">:</span> <span class="p">{</span>
    <span class="na">author</span><span class="p">:</span> <span class="p">(</span><span class="na">parent</span><span class="p">:</span> <span class="kr">any</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
      <span class="k">return</span> <span class="p">{</span>
        <span class="na">id</span><span class="p">:</span> <span class="nx">parent</span><span class="p">.</span><span class="nx">authorId</span><span class="p">,</span>
        <span class="na">name</span><span class="p">:</span> <span class="nx">parent</span><span class="p">.</span><span class="nx">authorId</span> <span class="o">==</span> <span class="dl">"</span><span class="s2">1</span><span class="dl">"</span> <span class="p">?</span> <span class="dl">"</span><span class="s2">James Carter</span><span class="dl">"</span> <span class="p">:</span> <span class="dl">"</span><span class="s2">Arthur Novotic</span><span class="dl">"</span><span class="p">,</span>
      <span class="p">};</span>
    <span class="p">},</span>
  <span class="p">},</span>
<span class="p">};</span>

<span class="k">async</span> <span class="kd">function</span> <span class="nx">main</span><span class="p">()</span> <span class="p">{</span>
  <span class="kd">const</span> <span class="nx">server</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">ApolloServer</span><span class="p">({</span> <span class="nx">typeDefs</span><span class="p">,</span> <span class="nx">resolvers</span> <span class="p">});</span>
  <span class="k">await</span> <span class="nx">server</span><span class="p">.</span><span class="nx">listen</span><span class="p">(</span><span class="mi">4000</span><span class="p">);</span>
  <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">Server started on http://localhost:4000</span><span class="dl">"</span><span class="p">);</span>
<span class="p">}</span>

<span class="nx">main</span><span class="p">();</span>
</pre></td></tr></tbody></table></code></pre></div></div>

<p>And from our React app, we query the resolver:</p>

<div class="language-ts highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
</pre></td><td class="rouge-code"><pre><span class="kd">const</span> <span class="nx">BOOKS</span> <span class="o">=</span> <span class="nx">gql</span><span class="s2">`
  query Query($bookId: ID) {
    books(id: $bookId) {
      title
      author {
        id
        name
      }
    }
  }
`</span><span class="p">;</span>

<span class="kd">const</span> <span class="nx">TestComp</span><span class="p">:</span> <span class="nx">FC</span> <span class="o">=</span> <span class="p">()</span> <span class="o">=&gt;</span> <span class="p">{</span>
  <span class="kd">const</span> <span class="p">[</span><span class="nx">id</span><span class="p">,</span> <span class="nx">setId</span><span class="p">]</span> <span class="o">=</span> <span class="nx">useState</span><span class="o">&lt;</span><span class="kr">string</span><span class="o">&gt;</span><span class="p">(</span><span class="dl">""</span><span class="p">);</span>
  <span class="kd">const</span> <span class="p">{</span> <span class="nx">loading</span><span class="p">,</span> <span class="nx">error</span><span class="p">,</span> <span class="nx">data</span> <span class="p">}</span> <span class="o">=</span> <span class="nx">useQuery</span><span class="o">&lt;</span><span class="p">{</span>
    <span class="na">books</span><span class="p">:</span> <span class="p">{</span> <span class="na">title</span><span class="p">:</span> <span class="kr">string</span><span class="p">;</span> <span class="nl">author</span><span class="p">:</span> <span class="p">{</span> <span class="na">id</span><span class="p">:</span> <span class="kr">string</span><span class="p">;</span> <span class="nl">name</span><span class="p">:</span> <span class="kr">string</span> <span class="p">}</span> <span class="p">}[];</span>
  <span class="p">}</span><span class="o">&gt;</span><span class="p">(</span><span class="nx">BOOKS</span><span class="p">,</span> <span class="p">{</span> <span class="na">variables</span><span class="p">:</span> <span class="p">{</span> <span class="na">bookId</span><span class="p">:</span> <span class="nx">id</span> <span class="p">},</span> <span class="na">fetchPolicy</span><span class="p">:</span> <span class="dl">"</span><span class="s2">cache-and-network</span><span class="dl">"</span> <span class="p">});</span>

  <span class="k">if</span> <span class="p">(</span><span class="nx">loading</span><span class="p">)</span> <span class="k">return</span> <span class="o">&lt;</span><span class="nx">p</span><span class="o">&gt;</span><span class="nx">Loading</span><span class="p">...</span><span class="o">&lt;</span><span class="sr">/p&gt;</span><span class="err">;
</span>  <span class="k">if</span> <span class="p">(</span><span class="nx">error</span><span class="p">)</span> <span class="k">return</span> <span class="o">&lt;</span><span class="nx">p</span><span class="o">&gt;</span><span class="na">Error</span> <span class="p">:(</span><span class="o">&lt;</span><span class="sr">/p&gt;</span><span class="err">;
</span>
  <span class="k">return</span> <span class="p">(</span>
    <span class="o">&lt;&gt;</span>
      <span class="o">&lt;</span><span class="nx">button</span> <span class="nx">onClick</span><span class="o">=</span><span class="p">{()</span> <span class="o">=&gt;</span> <span class="nx">setId</span><span class="p">(</span><span class="dl">""</span><span class="p">)}</span><span class="o">&gt;</span><span class="nx">Get</span> <span class="nx">all</span> <span class="nx">books</span><span class="o">&lt;</span><span class="sr">/button</span><span class="err">&gt;
</span>      <span class="o">&lt;</span><span class="nx">button</span> <span class="nx">onClick</span><span class="o">=</span><span class="p">{()</span> <span class="o">=&gt;</span> <span class="nx">setId</span><span class="p">(</span><span class="dl">"</span><span class="s2">1</span><span class="dl">"</span><span class="p">)}</span><span class="o">&gt;</span><span class="nx">Get</span> <span class="nx">book</span> <span class="mi">1</span><span class="o">&lt;</span><span class="sr">/button</span><span class="err">&gt;
</span>      <span class="p">{</span><span class="nx">data</span> <span class="o">&amp;&amp;</span>
        <span class="nx">data</span><span class="p">.</span><span class="nx">books</span><span class="p">.</span><span class="nx">map</span><span class="p">((</span><span class="nx">b</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
          <span class="k">return</span> <span class="p">(</span>
            <span class="o">&lt;</span><span class="nx">div</span><span class="o">&gt;</span>
              <span class="p">{</span><span class="nx">b</span><span class="p">.</span><span class="nx">title</span><span class="p">}</span> <span class="o">-</span> <span class="p">{</span><span class="nx">b</span><span class="p">.</span><span class="nx">author</span><span class="p">.</span><span class="nx">name</span><span class="p">}</span>
            <span class="o">&lt;</span><span class="sr">/div</span><span class="err">&gt;
</span>          <span class="p">);</span>
        <span class="p">})}</span>
    <span class="o">&lt;</span><span class="sr">/</span><span class="err">&gt;
</span>  <span class="p">);</span>
<span class="p">};</span>
</pre></td></tr></tbody></table></code></pre></div></div>

<p>If we use the default <code class="language-plaintext highlighter-rouge">cache-first</code>, after hitting once <code class="language-plaintext highlighter-rouge">Get all books</code> and hitting <code class="language-plaintext highlighter-rouge">Get book 1</code> buttons then back to <code class="language-plaintext highlighter-rouge">Get all books</code>, we can see that the backend is not consulted. If we change it to <code class="language-plaintext highlighter-rouge">cache-and-network</code>, we can see that the data comes from cache but the call is still made to the backend to update the data if it has changed.</p>

<p>And that conludes today’s post!</p>

<h2 id="conclusion">Conclusion</h2>

<p>In today’s post, we looked at fetch policies in Apollo client queries. We started by looking at how we could explore our in memory cache with Apollo client extension, and then moved on to look at each fetch policies available. I hope you liked this post and I’ll see you on the next one!</p>

<h2 id="external-sources">External Sources</h2>

<ul>
  <li><a href="https://www.apollographql.com/docs/react/">Apollo Client Documentation</a></li>
</ul>]]></content><author><name>kimserey</name></author><category term="typescript" /><category term="graphql" /><category term="react" /><summary type="html"><![CDATA[Last week we looked at Apollo Client and how it could be used to manage queries to GraphQL server. In today’s post, we’ll look at the different fetching policies provided to manage query data and caching.]]></summary></entry><entry><title type="html">Query Graphql With Apollo Client React</title><link href="https://kimserey.lam.gitlab.io/typescript/graphql/react/2022/04/29/query-graphql-with-apollo-client-react.html" rel="alternate" type="text/html" title="Query Graphql With Apollo Client React" /><published>2022-04-29T00:00:00-05:00</published><updated>2022-04-29T00:00:00-05:00</updated><id>https://kimserey.lam.gitlab.io/typescript/graphql/react/2022/04/29/query-graphql-with-apollo-client-react</id><content type="html" xml:base="https://kimserey.lam.gitlab.io/typescript/graphql/react/2022/04/29/query-graphql-with-apollo-client-react.html"><![CDATA[<p>Apollo client allows us to easily manage our GraphQL queries and data from the clientside. It provides functionalities such as caching, loading state and data propagation to components and most importantly; is compatible with all major UI frameworks. In today’s post, we’ll look at how we can simply hook Apollo client in a React application and use it to query our GraphQL server.</p>

<!--more-->

<ul>
  <li><a href="#simple-server">Simple Server</a></li>
  <li><a href="#setup-apollo-client">Setup Apollo Client</a></li>
  <li><a href="#query-server-with-query-hook">Query Server With Query Hook</a></li>
</ul>

<h2 id="simple-server"><a href="#simple-server">Simple Server</a></h2>

<p>We start first by re-creating our previous server using Apollo server (if you haven’t done that, <a href="https://kimsereylam.com/typescript/graphql/2021/10/29/get-started-with-apollo-server-in-typescript.html">you can follow our previous post</a>).</p>

<div class="language-ts highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
</pre></td><td class="rouge-code"><pre><span class="k">import</span> <span class="p">{</span> <span class="nx">ApolloServer</span><span class="p">,</span> <span class="nx">gql</span> <span class="p">}</span> <span class="k">from</span> <span class="dl">"</span><span class="s2">apollo-server</span><span class="dl">"</span><span class="p">;</span>

<span class="kd">const</span> <span class="nx">typeDefs</span> <span class="o">=</span> <span class="nx">gql</span><span class="s2">`
  type Person {
    id: ID!
    name: String!
  }

  type Book {
    title: String
    author: Person
  }

  type Query {
    books: [Book]
  }
`</span><span class="p">;</span>

<span class="kd">const</span> <span class="nx">resolvers</span> <span class="o">=</span> <span class="p">{</span>
  <span class="na">Query</span><span class="p">:</span> <span class="p">{</span>
    <span class="na">books</span><span class="p">:</span> <span class="p">()</span> <span class="o">=&gt;</span> <span class="p">[</span>
      <span class="p">{</span>
        <span class="na">title</span><span class="p">:</span> <span class="dl">"</span><span class="s2">Made of Wolves</span><span class="dl">"</span><span class="p">,</span>
        <span class="na">authorId</span><span class="p">:</span> <span class="dl">"</span><span class="s2">1</span><span class="dl">"</span><span class="p">,</span>
      <span class="p">},</span>
      <span class="p">{</span>
        <span class="na">title</span><span class="p">:</span> <span class="dl">"</span><span class="s2">The Visitor in the City</span><span class="dl">"</span><span class="p">,</span>
        <span class="na">authorId</span><span class="p">:</span> <span class="dl">"</span><span class="s2">2</span><span class="dl">"</span><span class="p">,</span>
      <span class="p">},</span>
    <span class="p">],</span>
  <span class="p">},</span>
  <span class="na">Book</span><span class="p">:</span> <span class="p">{</span>
    <span class="na">author</span><span class="p">:</span> <span class="p">(</span><span class="na">parent</span><span class="p">:</span> <span class="kr">any</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
      <span class="k">return</span> <span class="p">{</span>
        <span class="na">id</span><span class="p">:</span> <span class="nx">parent</span><span class="p">.</span><span class="nx">authorId</span><span class="p">,</span>
        <span class="na">name</span><span class="p">:</span> <span class="nx">parent</span><span class="p">.</span><span class="nx">authorId</span> <span class="o">==</span> <span class="dl">"</span><span class="s2">1</span><span class="dl">"</span> <span class="p">?</span> <span class="dl">"</span><span class="s2">James Carter</span><span class="dl">"</span> <span class="p">:</span> <span class="dl">"</span><span class="s2">Arthur Novotic</span><span class="dl">"</span><span class="p">,</span>
      <span class="p">};</span>
    <span class="p">},</span>
  <span class="p">},</span>
<span class="p">};</span>

<span class="k">async</span> <span class="kd">function</span> <span class="nx">main</span><span class="p">()</span> <span class="p">{</span>
  <span class="kd">const</span> <span class="nx">server</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">ApolloServer</span><span class="p">({</span> <span class="nx">typeDefs</span><span class="p">,</span> <span class="nx">resolvers</span> <span class="p">});</span>
  <span class="k">await</span> <span class="nx">server</span><span class="p">.</span><span class="nx">listen</span><span class="p">(</span><span class="mi">4000</span><span class="p">);</span>
  <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">Server started on http://localhost:4000</span><span class="dl">"</span><span class="p">);</span>
<span class="p">}</span>

<span class="nx">main</span><span class="p">();</span>
</pre></td></tr></tbody></table></code></pre></div></div>

<p>This will setup a GraphQL server with a single query <code class="language-plaintext highlighter-rouge">books</code> and a field resolver for <code class="language-plaintext highlighter-rouge">Book.author</code>. We can now start to build our frontend to query our server.</p>

<h2 id="setup-apollo-client"><a href="#setup-apollo-client">Setup Apollo Client</a></h2>

<p>We start first by installing Apollo client:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
</pre></td><td class="rouge-code"><pre>npm install @apollo/client graphql
</pre></td></tr></tbody></table></code></pre></div></div>

<p>And we then create a client in our <code class="language-plaintext highlighter-rouge">index.tsx</code> file:</p>

<div class="language-ts highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
</pre></td><td class="rouge-code"><pre><span class="k">import</span> <span class="p">{</span>
  <span class="nx">ApolloClient</span><span class="p">,</span>
  <span class="nx">InMemoryCache</span><span class="p">,</span>
  <span class="nx">ApolloProvider</span><span class="p">,</span>
  <span class="nx">useQuery</span><span class="p">,</span>
  <span class="nx">gql</span><span class="p">,</span>
<span class="p">}</span> <span class="k">from</span> <span class="dl">"</span><span class="s2">@apollo/client</span><span class="dl">"</span><span class="p">;</span>

<span class="kd">const</span> <span class="nx">client</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">ApolloClient</span><span class="p">({</span>
  <span class="na">uri</span><span class="p">:</span> <span class="dl">"</span><span class="s2">http://localhost:4000</span><span class="dl">"</span><span class="p">,</span>
  <span class="na">cache</span><span class="p">:</span> <span class="k">new</span> <span class="nx">InMemoryCache</span><span class="p">(),</span>
<span class="p">});</span>
</pre></td></tr></tbody></table></code></pre></div></div>

<p>If we add a query on the client, we can test that the client is working:</p>

<div class="language-ts highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
</pre></td><td class="rouge-code"><pre><span class="nx">client</span>
  <span class="p">.</span><span class="nx">query</span><span class="p">({</span>
    <span class="na">query</span><span class="p">:</span> <span class="nx">gql</span><span class="s2">`
      query Query {
        books {
          title
          author {
            id
            name
          }
        }
      }
    `</span><span class="p">,</span>
  <span class="p">})</span>
  <span class="p">.</span><span class="nx">then</span><span class="p">((</span><span class="nx">result</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">result</span><span class="p">));</span>
</pre></td></tr></tbody></table></code></pre></div></div>

<p>And we’ll see the result in the console.</p>

<h2 id="query-server-with-query-hook"><a href="#query-server-with-query-hook">Query Server With Query Hook</a></h2>

<p>Now querying directly with the client isn’t the recommended way. Instead, we’ll use the build-in hooks provided. For us as we have a query, we’ll use <code class="language-plaintext highlighter-rouge">useQuery</code>.</p>

<p>Before being able to use hooks, we need to register the client by wrapping our app into the <code class="language-plaintext highlighter-rouge">ApolloProvider</code>:</p>

<div class="language-ts highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
</pre></td><td class="rouge-code"><pre><span class="kd">const</span> <span class="nx">client</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">ApolloClient</span><span class="p">({</span>
  <span class="na">uri</span><span class="p">:</span> <span class="dl">"</span><span class="s2">http://localhost:4000</span><span class="dl">"</span><span class="p">,</span>
  <span class="na">cache</span><span class="p">:</span> <span class="k">new</span> <span class="nx">InMemoryCache</span><span class="p">(),</span>
<span class="p">});</span>

<span class="nx">ReactDOM</span><span class="p">.</span><span class="nx">render</span><span class="p">(</span>
  <span class="o">&lt;</span><span class="nx">React</span><span class="p">.</span><span class="nx">StrictMode</span><span class="o">&gt;</span>
    <span class="o">&lt;</span><span class="nx">ApolloProvider</span> <span class="nx">client</span><span class="o">=</span><span class="p">{</span><span class="nx">client</span><span class="p">}</span><span class="o">&gt;</span>
      <span class="o">&lt;</span><span class="nx">App</span> <span class="o">/&gt;</span>
    <span class="o">&lt;</span><span class="sr">/ApolloProvider</span><span class="err">&gt;
</span>  <span class="o">&lt;</span><span class="sr">/React.StrictMode&gt;</span><span class="err">,
</span>  <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="dl">"</span><span class="s2">root</span><span class="dl">"</span><span class="p">)</span>
<span class="p">);</span>
</pre></td></tr></tbody></table></code></pre></div></div>

<p>And we can then use <code class="language-plaintext highlighter-rouge">useQuery</code>:</p>

<div class="language-ts highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
</pre></td><td class="rouge-code"><pre><span class="k">import</span> <span class="p">{</span> <span class="nx">gql</span><span class="p">,</span> <span class="nx">useQuery</span> <span class="p">}</span> <span class="k">from</span> <span class="dl">"</span><span class="s2">@apollo/client</span><span class="dl">"</span><span class="p">;</span>
<span class="k">import</span> <span class="nx">React</span><span class="p">,</span> <span class="p">{</span> <span class="nx">FC</span> <span class="p">}</span> <span class="k">from</span> <span class="dl">"</span><span class="s2">react</span><span class="dl">"</span><span class="p">;</span>

<span class="kd">const</span> <span class="nx">BOOKS</span> <span class="o">=</span> <span class="nx">gql</span><span class="s2">`
  query GetBooks {
    books {
      title
      author {
        id
        name
      }
    }
  }
`</span><span class="p">;</span>

<span class="kd">const</span> <span class="nx">TestComp</span><span class="p">:</span> <span class="nx">FC</span> <span class="o">=</span> <span class="p">()</span> <span class="o">=&gt;</span> <span class="p">{</span>
  <span class="kd">const</span> <span class="p">{</span> <span class="nx">data</span><span class="p">,</span> <span class="nx">loading</span><span class="p">,</span> <span class="nx">error</span> <span class="p">}</span> <span class="o">=</span> <span class="nx">useQuery</span><span class="o">&lt;</span><span class="p">{</span>
    <span class="na">books</span><span class="p">:</span> <span class="p">{</span> <span class="na">title</span><span class="p">:</span> <span class="kr">string</span><span class="p">;</span> <span class="nl">author</span><span class="p">:</span> <span class="p">{</span> <span class="na">id</span><span class="p">:</span> <span class="kr">string</span><span class="p">;</span> <span class="nl">name</span><span class="p">:</span> <span class="kr">string</span> <span class="p">}</span> <span class="p">}[];</span>
  <span class="p">}</span><span class="o">&gt;</span><span class="p">(</span><span class="nx">BOOKS</span><span class="p">);</span>

  <span class="k">if</span> <span class="p">(</span><span class="nx">loading</span><span class="p">)</span> <span class="k">return</span> <span class="o">&lt;</span><span class="nx">p</span><span class="o">&gt;</span><span class="nx">Loading</span><span class="p">...</span><span class="o">&lt;</span><span class="sr">/p&gt;</span><span class="err">;
</span>  <span class="k">if</span> <span class="p">(</span><span class="nx">error</span><span class="p">)</span> <span class="k">return</span> <span class="o">&lt;</span><span class="nx">p</span><span class="o">&gt;</span><span class="na">Error</span> <span class="p">:(</span><span class="o">&lt;</span><span class="sr">/p&gt;</span><span class="err">;
</span>
  <span class="k">return</span> <span class="p">(</span>
    <span class="o">&lt;&gt;</span>
      <span class="p">{</span><span class="nx">data</span> <span class="o">&amp;&amp;</span>
        <span class="nx">data</span><span class="p">.</span><span class="nx">books</span><span class="p">.</span><span class="nx">map</span><span class="p">((</span><span class="nx">b</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
          <span class="k">return</span> <span class="p">(</span>
            <span class="o">&lt;</span><span class="nx">div</span><span class="o">&gt;</span>
              <span class="p">{</span><span class="nx">b</span><span class="p">.</span><span class="nx">title</span><span class="p">}</span> <span class="o">-</span> <span class="p">{</span><span class="nx">b</span><span class="p">.</span><span class="nx">author</span><span class="p">.</span><span class="nx">name</span><span class="p">}</span>
            <span class="o">&lt;</span><span class="sr">/div</span><span class="err">&gt;
</span>          <span class="p">);</span>
        <span class="p">})}</span>
    <span class="o">&lt;</span><span class="sr">/</span><span class="err">&gt;
</span>  <span class="p">);</span>
<span class="p">};</span>

<span class="kd">function</span> <span class="nx">App</span><span class="p">()</span> <span class="p">{</span>
  <span class="k">return</span> <span class="p">(</span>
    <span class="o">&lt;</span><span class="nx">div</span> <span class="nx">className</span><span class="o">=</span><span class="dl">"</span><span class="s2">App</span><span class="dl">"</span><span class="o">&gt;</span>
      <span class="o">&lt;</span><span class="nx">TestComp</span><span class="o">&gt;&lt;</span><span class="sr">/TestComp</span><span class="err">&gt;
</span>    <span class="o">&lt;</span><span class="sr">/div</span><span class="err">&gt;
</span>  <span class="p">);</span>
<span class="p">}</span>

<span class="k">export</span> <span class="k">default</span> <span class="nx">App</span><span class="p">;</span>
</pre></td></tr></tbody></table></code></pre></div></div>

<p>We can see that <code class="language-plaintext highlighter-rouge">useQuery</code> takes a <code class="language-plaintext highlighter-rouge">gql</code> query as parameter, which is the definition of our GraphQL query. The advantage of using <code class="language-plaintext highlighter-rouge">useQuery</code> hook is tha <code class="language-plaintext highlighter-rouge">data</code>, <code class="language-plaintext highlighter-rouge">loading</code> and <code class="language-plaintext highlighter-rouge">error</code> will get update as the client queries the data which will in turn trigger a rendering of the component.</p>

<p>This allows us to create specific logic to handle querying, error state and display of data.</p>

<p>Other than the <code class="language-plaintext highlighter-rouge">useQuery</code> hook, we also have access to the <code class="language-plaintext highlighter-rouge">useMutation</code> hook for GraphQL mutations and plenty of other configurations for the client.</p>

<p>And that concludes today’s post!</p>

<h2 id="conclusion">Conclusion</h2>

<p>Today we looked at how we could setup Apollo Client to query a GraphQL server. We started by a quick recap on setting up a server and then moved on to setup Apollo Client and completed the post by looking at the query hook provided by Apollo Client. I hope you liked this post and I’ll see you on the next one!</p>

<h2 id="external-sources">External Sources</h2>

<ul>
  <li><a href="https://www.apollographql.com/docs/react/">Apollo Client Documentation</a></li>
</ul>]]></content><author><name>kimserey</name></author><category term="typescript" /><category term="graphql" /><category term="react" /><summary type="html"><![CDATA[Apollo client allows us to easily manage our GraphQL queries and data from the clientside. It provides functionalities such as caching, loading state and data propagation to components and most importantly; is compatible with all major UI frameworks. In today’s post, we’ll look at how we can simply hook Apollo client in a React application and use it to query our GraphQL server.]]></summary></entry><entry><title type="html">Common Table Expression In Postgres</title><link href="https://kimserey.lam.gitlab.io/postgres/2022/04/22/common-table-expression-in-postgres.html" rel="alternate" type="text/html" title="Common Table Expression In Postgres" /><published>2022-04-22T00:00:00-05:00</published><updated>2022-04-22T00:00:00-05:00</updated><id>https://kimserey.lam.gitlab.io/postgres/2022/04/22/common-table-expression-in-postgres</id><content type="html" xml:base="https://kimserey.lam.gitlab.io/postgres/2022/04/22/common-table-expression-in-postgres.html"><![CDATA[<p>Common table expression, also called <code class="language-plaintext highlighter-rouge">WITH</code> queries, can be used to create auxiliary queries that can be used in larger queries. They can be used to breakdown complex queries into multiple simpler queries which are then used in a primary statement or they can also be used to write recursive queries. In today’s post, we will look at how to define CTE with examples in Postgres.</p>

<!--more-->

<ul>
  <li><a href="#breakdown-complex-queries">Breakdown Complex Queries</a></li>
  <li><a href="#recursive-queries">Recursive Queries</a></li>
</ul>

<h2 id="breakdown-complex-queries"><a href="#breakdown-complex-queries">Breakdown Complex Queries</a></h2>

<p>Breaking down complex queries using common table expression can be done as followed:</p>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
</pre></td><td class="rouge-code"><pre><span class="k">with</span> <span class="n">salaries</span> <span class="k">as</span> <span class="p">(</span>
  <span class="k">select</span>
    <span class="n">id</span><span class="p">,</span>
    <span class="n">title</span><span class="p">,</span>
    <span class="p">(</span><span class="k">case</span> <span class="k">when</span> <span class="n">remuneration</span> <span class="o">&lt;</span> <span class="mi">100</span> <span class="k">then</span> <span class="s1">'low'</span> <span class="k">when</span> <span class="n">remuneration</span> <span class="o">&lt;</span> <span class="mi">500</span> <span class="k">then</span> <span class="s1">'medium'</span> <span class="k">else</span> <span class="s1">'high'</span> <span class="k">end</span><span class="p">)</span> <span class="k">as</span> <span class="n">category</span>
  <span class="k">from</span> <span class="n">job</span>
<span class="p">),</span> <span class="n">groups</span> <span class="k">as</span> <span class="p">(</span>
  <span class="k">select</span>
    <span class="k">count</span><span class="p">(</span><span class="o">*</span><span class="p">)</span> <span class="k">as</span> <span class="n">job_count</span><span class="p">,</span>
    <span class="k">max</span><span class="p">(</span><span class="n">category</span><span class="p">)</span> <span class="k">as</span> <span class="n">category</span>
  <span class="k">from</span> <span class="n">salaries</span>
  <span class="k">group</span> <span class="k">by</span> <span class="n">category</span>
<span class="p">)</span>
<span class="k">select</span> <span class="o">*</span> <span class="k">from</span> <span class="n">groups</span>
<span class="k">where</span> <span class="n">category</span> <span class="o">!=</span> <span class="s1">'low'</span>
</pre></td></tr></tbody></table></code></pre></div></div>

<p>We start by using <code class="language-plaintext highlighter-rouge">with</code> keyword to create a table result <code class="language-plaintext highlighter-rouge">salaries</code> which will contain the jobs with a salary categorised between <code class="language-plaintext highlighter-rouge">low</code>, <code class="language-plaintext highlighter-rouge">medium</code> and <code class="language-plaintext highlighter-rouge">high</code>.</p>

<p>We then continue with another common table by separating with a comma, and use <code class="language-plaintext highlighter-rouge">salaries</code> to group by the category.</p>

<p>And lastly we use the common tables into the primary statement which exclude <code class="language-plaintext highlighter-rouge">low</code>.</p>

<p>We can see how this notation can be used to breakdown queries into small parts and assembling them to be usable in the primary statement.</p>

<h2 id="recursive-queries"><a href="#recursive-queries">Recursive Queries</a></h2>

<p>Another usage of CTE is to execute recursive queries. The format of a recursive query is as followed:</p>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
</pre></td><td class="rouge-code"><pre><span class="k">with</span> <span class="k">recursive</span> <span class="n">t</span><span class="p">(</span><span class="n">n</span><span class="p">)</span> <span class="k">as</span> <span class="p">(</span>
    <span class="k">values</span> <span class="p">(</span><span class="mi">1</span><span class="p">)</span>
  <span class="k">union</span> <span class="k">all</span>
    <span class="k">select</span> <span class="n">n</span><span class="o">+</span><span class="mi">1</span> <span class="k">from</span> <span class="n">t</span> <span class="k">where</span> <span class="n">n</span> <span class="o">&lt;</span> <span class="mi">10</span>
<span class="p">)</span>
<span class="k">select</span> <span class="o">*</span> <span class="k">from</span> <span class="n">t</span>
</pre></td></tr></tbody></table></code></pre></div></div>

<p>which will return:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
</pre></td><td class="rouge-code"><pre>+----+
| n  |
|----|
| 1  |
| 2  |
| 3  |
| 4  |
| 5  |
| 6  |
| 7  |
| 8  |
| 9  |
| 10 |
+----+
SELECT 10
Time: 0.003s
</pre></td></tr></tbody></table></code></pre></div></div>

<p>The definition of the recursive CTE is a non-recursive statement, followed by <code class="language-plaintext highlighter-rouge">union</code> or <code class="language-plaintext highlighter-rouge">union all</code> and a recursive statement.</p>

<p>The first non-recursive statement is the initial dataset extracted, where the recursive statement will be applied to. At each application of the recursive statement, the data is appended following either <code class="language-plaintext highlighter-rouge">union</code> or <code class="language-plaintext highlighter-rouge">union all</code>, and the process is repeated until there is no more item returned by the recursive statement.</p>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
</pre></td><td class="rouge-code"><pre><span class="k">with</span> <span class="k">recursive</span> <span class="n">all_jobs</span> <span class="k">as</span> <span class="p">(</span>
     <span class="k">select</span> <span class="n">id</span><span class="p">,</span> <span class="n">title</span><span class="p">,</span> <span class="n">parentJobId</span> <span class="k">from</span> <span class="n">job</span> <span class="k">where</span> <span class="n">id</span> <span class="o">=</span> <span class="s1">'1'</span>
   <span class="k">union</span> <span class="k">all</span>
     <span class="k">select</span> <span class="n">j</span><span class="p">.</span><span class="n">id</span><span class="p">,</span> <span class="n">j</span><span class="p">.</span><span class="n">title</span><span class="p">,</span> <span class="n">j</span><span class="p">.</span><span class="n">parentJobId</span>
     <span class="k">from</span> <span class="n">job</span> <span class="n">j</span>
     <span class="k">join</span> <span class="n">all_jobs</span> <span class="n">pj</span> <span class="k">on</span> <span class="n">pj</span><span class="p">.</span><span class="n">id</span> <span class="o">=</span> <span class="n">j</span><span class="p">.</span><span class="n">parentJobId</span>
 <span class="p">)</span>
 <span class="k">select</span> <span class="o">*</span> <span class="k">from</span> <span class="n">all_jobs</span>
</pre></td></tr></tbody></table></code></pre></div></div>

<p>With this query we are able to recursively query all the children of job <code class="language-plaintext highlighter-rouge">1</code> at all levels. This is achieved by first getting job <code class="language-plaintext highlighter-rouge">1</code> in the non-recursive statement, then on the recursive statement, join the table back and retrieve rows that have the jobs as parent.</p>

<p>Lastly just like regular CTE, the recursive CTE can also be combined:</p>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
</pre></td><td class="rouge-code"><pre><span class="k">with</span> <span class="k">recursive</span> <span class="n">all_jobs</span> <span class="k">as</span> <span class="p">(</span>
     <span class="k">select</span> <span class="n">id</span><span class="p">,</span> <span class="n">title</span><span class="p">,</span> <span class="n">parentJobId</span><span class="p">,</span> <span class="n">remuneration</span> <span class="k">from</span> <span class="n">job</span> <span class="k">where</span> <span class="n">id</span> <span class="o">=</span> <span class="s1">'1'</span>
   <span class="k">union</span> <span class="k">all</span>
     <span class="k">select</span> <span class="n">j</span><span class="p">.</span><span class="n">id</span><span class="p">,</span> <span class="n">j</span><span class="p">.</span><span class="n">title</span><span class="p">,</span> <span class="n">j</span><span class="p">.</span><span class="n">parentJobId</span><span class="p">,</span> <span class="n">j</span><span class="p">.</span><span class="n">remuneration</span>
     <span class="k">from</span> <span class="n">job</span> <span class="n">j</span>
     <span class="k">join</span> <span class="n">all_jobs</span> <span class="n">pj</span> <span class="k">on</span> <span class="n">pj</span><span class="p">.</span><span class="n">id</span> <span class="o">=</span> <span class="n">j</span><span class="p">.</span><span class="n">parentJobId</span>
 <span class="p">),</span> <span class="n">salaries</span> <span class="k">as</span> <span class="p">(</span>
  <span class="k">select</span>
    <span class="n">id</span><span class="p">,</span>
    <span class="n">title</span><span class="p">,</span>
    <span class="n">parentJobId</span><span class="p">,</span>
    <span class="p">(</span><span class="k">case</span> <span class="k">when</span> <span class="n">remuneration</span> <span class="o">&lt;</span> <span class="mi">100</span> <span class="k">then</span> <span class="s1">'low'</span> <span class="k">when</span> <span class="n">remuneration</span> <span class="o">&lt;</span> <span class="mi">500</span> <span class="k">then</span> <span class="s1">'medium'</span> <span class="k">else</span> <span class="s1">'high'</span> <span class="k">end</span><span class="p">)</span> <span class="k">as</span> <span class="n">category</span>
  <span class="k">from</span> <span class="n">all_jobs</span>
<span class="p">)</span>
<span class="k">select</span> <span class="o">*</span> <span class="k">from</span> <span class="n">salaries</span>
</pre></td></tr></tbody></table></code></pre></div></div>

<p>Just as an example we added our previous auxiliary statement which categories the jobs.</p>

<p>And that concludes today’s post on CTE!</p>

<h2 id="conclusion">Conclusion</h2>

<p>In today’s post, we looked at Postgres common table expression. We started by looking at how they could be used to breakdown complex queries in smaller pieces and we then moved on to look at how we could write recursive queries. I hope you liked this post, and I’ll see you on the next one!</p>

<h2 id="related-posts">Related Posts</h2>

<ul>
  <li><a href="https://kimsereylam.com/sqlite/2020/03/13/recursive-query-in-sqlite-with-cte.html">Recursive Query In Sqlite With Cte</a></li>
</ul>

<h2 id="external-sources">External Sources</h2>

<ul>
  <li><a href="https://www.postgresql.org/docs/current/queries-with.html">Postgres Documentation</a></li>
</ul>]]></content><author><name>kimserey</name></author><category term="postgres" /><summary type="html"><![CDATA[Common table expression, also called WITH queries, can be used to create auxiliary queries that can be used in larger queries. They can be used to breakdown complex queries into multiple simpler queries which are then used in a primary statement or they can also be used to write recursive queries. In today’s post, we will look at how to define CTE with examples in Postgres.]]></summary></entry><entry><title type="html">React Reducer Hook</title><link href="https://kimserey.lam.gitlab.io/react/typescript/2022/04/15/react-reducer-hook.html" rel="alternate" type="text/html" title="React Reducer Hook" /><published>2022-04-15T00:00:00-05:00</published><updated>2022-04-15T00:00:00-05:00</updated><id>https://kimserey.lam.gitlab.io/react/typescript/2022/04/15/react-reducer-hook</id><content type="html" xml:base="https://kimserey.lam.gitlab.io/react/typescript/2022/04/15/react-reducer-hook.html"><![CDATA[<p><code class="language-plaintext highlighter-rouge">useReducer</code> hook in React allows us to manage state in a redux manner. This is useful for handling complex state in a single object, as opposed to <code class="language-plaintext highlighter-rouge">useState</code> which is better used with single variable state. With <code class="language-plaintext highlighter-rouge">useReducer</code>, we can define a reducer, a set of actions to interact with the state and use a dispatcher to dispatch the actions from our component. In today’s post we will look at how we can use <code class="language-plaintext highlighter-rouge">useReducer</code> with example.</p>

<!--more-->

<ul>
  <li><a href="#userreducer-hook"><code class="language-plaintext highlighter-rouge">useReducer</code> Hook</a></li>
  <li><a href="#invoke-actions-from-children">Invoke Actions From Children</a></li>
</ul>

<h2 id="usereducer-hook"><a href="#userreducer-hook"><code class="language-plaintext highlighter-rouge">useReducer</code> Hook</a></h2>

<p><code class="language-plaintext highlighter-rouge">useReduce</code> provides a way to manage state in a Redux manner. The main components are the reducer and the actions. We start by defininig the state in an interface:</p>

<div class="language-ts highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
</pre></td><td class="rouge-code"><pre><span class="kr">interface</span> <span class="nx">CounterState</span> <span class="p">{</span>
  <span class="nl">count</span><span class="p">:</span> <span class="kr">number</span><span class="p">;</span>
<span class="p">}</span>
</pre></td></tr></tbody></table></code></pre></div></div>

<p>Then we can define the actions that we will use to modify the state:</p>

<div class="language-ts highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
</pre></td><td class="rouge-code"><pre><span class="kr">interface</span> <span class="nx">IncrementCounter</span> <span class="p">{</span>
  <span class="nl">kind</span><span class="p">:</span> <span class="dl">"</span><span class="s2">Increment</span><span class="dl">"</span><span class="p">;</span>
<span class="p">}</span>

<span class="kr">interface</span> <span class="nx">DecrementCounter</span> <span class="p">{</span>
  <span class="nl">kind</span><span class="p">:</span> <span class="dl">"</span><span class="s2">Decrement</span><span class="dl">"</span><span class="p">;</span>
<span class="p">}</span>

<span class="kr">interface</span> <span class="nx">ResetCount</span> <span class="p">{</span>
  <span class="nl">kind</span><span class="p">:</span> <span class="dl">"</span><span class="s2">Reset</span><span class="dl">"</span><span class="p">;</span>
<span class="p">}</span>

<span class="kd">type</span> <span class="nx">CounterAction</span> <span class="o">=</span> <span class="nx">IncrementCounter</span> <span class="o">|</span> <span class="nx">DecrementCounter</span> <span class="o">|</span> <span class="nx">ResetCount</span><span class="p">;</span>
</pre></td></tr></tbody></table></code></pre></div></div>

<p>The actions should ideally all share a property <code class="language-plaintext highlighter-rouge">kind</code> or <code class="language-plaintext highlighter-rouge">type</code> which will be used in the reducer to identify which action has been dispatch.</p>

<p>Next we define the reducer:</p>

<div class="language-ts highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
</pre></td><td class="rouge-code"><pre><span class="kd">const</span> <span class="nx">reducer</span> <span class="o">=</span> <span class="p">(</span><span class="nx">state</span><span class="p">:</span> <span class="nx">CounterState</span><span class="p">,</span> <span class="nx">action</span><span class="p">:</span> <span class="nx">CounterAction</span><span class="p">):</span> <span class="nx">CounterState</span> <span class="o">=&gt;</span> <span class="p">{</span>
  <span class="k">switch</span> <span class="p">(</span><span class="nx">action</span><span class="p">.</span><span class="nx">kind</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">case</span> <span class="dl">"</span><span class="s2">Increment</span><span class="dl">"</span><span class="p">:</span>
      <span class="k">return</span> <span class="p">{</span> <span class="na">count</span><span class="p">:</span> <span class="nx">state</span><span class="p">.</span><span class="nx">count</span> <span class="o">+</span> <span class="mi">1</span> <span class="p">};</span>
    <span class="k">case</span> <span class="dl">"</span><span class="s2">Decrement</span><span class="dl">"</span><span class="p">:</span>
      <span class="k">return</span> <span class="p">{</span> <span class="na">count</span><span class="p">:</span> <span class="nx">state</span><span class="p">.</span><span class="nx">count</span> <span class="o">-</span> <span class="mi">1</span> <span class="p">};</span>
    <span class="k">case</span> <span class="dl">"</span><span class="s2">Reset</span><span class="dl">"</span><span class="p">:</span>
      <span class="k">return</span> <span class="p">{</span> <span class="na">count</span><span class="p">:</span> <span class="mi">0</span> <span class="p">};</span>
  <span class="p">}</span>
<span class="p">};</span>
</pre></td></tr></tbody></table></code></pre></div></div>

<p>We do a switch on the property that determines the action to execute and we apply to the state. A reducer is a function which takes the previous state and the action, and return the next state.</p>

<p>We now have all the components to use <code class="language-plaintext highlighter-rouge">useReducer</code>:</p>

<div class="language-ts highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
</pre></td><td class="rouge-code"><pre><span class="kd">const</span> <span class="nx">App</span><span class="p">:</span> <span class="nx">FC</span> <span class="o">=</span> <span class="p">()</span> <span class="o">=&gt;</span> <span class="p">{</span>
  <span class="kd">const</span> <span class="nx">initialState</span> <span class="o">=</span> <span class="p">{</span>
    <span class="na">count</span><span class="p">:</span> <span class="mi">0</span><span class="p">,</span>
  <span class="p">};</span>

  <span class="kd">const</span> <span class="p">[</span><span class="nx">state</span><span class="p">,</span> <span class="nx">dispatch</span><span class="p">]</span> <span class="o">=</span> <span class="nx">useReducer</span><span class="p">(</span><span class="nx">reducer</span><span class="p">,</span> <span class="nx">initialState</span><span class="p">);</span>

  <span class="k">return</span> <span class="p">(</span>
    <span class="o">&lt;&gt;</span>
      <span class="o">&lt;</span><span class="nx">button</span> <span class="nx">onClick</span><span class="o">=</span><span class="p">{()</span> <span class="o">=&gt;</span> <span class="nx">dispatch</span><span class="p">({</span> <span class="na">kind</span><span class="p">:</span> <span class="dl">"</span><span class="s2">Increment</span><span class="dl">"</span> <span class="p">})}</span><span class="o">&gt;</span><span class="nx">Increment</span><span class="o">&lt;</span><span class="sr">/button</span><span class="err">&gt;
</span>      <span class="o">&lt;</span><span class="nx">button</span> <span class="nx">onClick</span><span class="o">=</span><span class="p">{()</span> <span class="o">=&gt;</span> <span class="nx">dispatch</span><span class="p">({</span> <span class="na">kind</span><span class="p">:</span> <span class="dl">"</span><span class="s2">Decrement</span><span class="dl">"</span> <span class="p">})}</span><span class="o">&gt;</span><span class="nx">Decrement</span><span class="o">&lt;</span><span class="sr">/button</span><span class="err">&gt;
</span>      <span class="o">&lt;</span><span class="nx">button</span> <span class="nx">onClick</span><span class="o">=</span><span class="p">{()</span> <span class="o">=&gt;</span> <span class="nx">dispatch</span><span class="p">({</span> <span class="na">kind</span><span class="p">:</span> <span class="dl">"</span><span class="s2">Reset</span><span class="dl">"</span> <span class="p">})}</span><span class="o">&gt;</span><span class="nx">Reset</span><span class="o">&lt;</span><span class="sr">/button</span><span class="err">&gt;
</span>      <span class="o">&lt;</span><span class="nx">p</span><span class="o">&gt;</span><span class="p">{</span><span class="nx">state</span><span class="p">.</span><span class="nx">count</span><span class="p">}</span><span class="o">&lt;</span><span class="sr">/p</span><span class="err">&gt;
</span>    <span class="o">&lt;</span><span class="sr">/</span><span class="err">&gt;
</span>  <span class="p">);</span>
<span class="p">};</span>
</pre></td></tr></tbody></table></code></pre></div></div>

<p>We can see that <code class="language-plaintext highlighter-rouge">useReducer</code> returned a tuple composed by the state and a <code class="language-plaintext highlighter-rouge">dispatch</code> function. The <code class="language-plaintext highlighter-rouge">dispatch</code> function is used to dispatch an action from our component.</p>

<h2 id="invoke-actions-from-children"><a href="#invoke-actions-from-children">Invoke Actions From Children</a></h2>

<p>The advantage of using a reducer with actions is that we can pass down <code class="language-plaintext highlighter-rouge">dispatch</code> to provide all functionalities to child components.</p>

<div class="language-ts highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
</pre></td><td class="rouge-code"><pre><span class="kd">const</span> <span class="nx">ButtonComponent</span><span class="p">:</span> <span class="nx">FC</span><span class="o">&lt;</span><span class="p">{</span> <span class="na">dispatch</span><span class="p">:</span> <span class="nx">Dispatch</span><span class="o">&lt;</span><span class="nx">CounterAction</span><span class="o">&gt;</span> <span class="p">}</span><span class="o">&gt;</span> <span class="o">=</span> <span class="p">({</span>
  <span class="nx">dispatch</span><span class="p">,</span>
<span class="p">})</span> <span class="o">=&gt;</span> <span class="p">{</span>
  <span class="k">return</span> <span class="p">(</span>
    <span class="o">&lt;</span><span class="nx">div</span><span class="o">&gt;</span>
      <span class="o">&lt;</span><span class="nx">button</span> <span class="nx">onClick</span><span class="o">=</span><span class="p">{()</span> <span class="o">=&gt;</span> <span class="nx">dispatch</span><span class="p">({</span> <span class="na">kind</span><span class="p">:</span> <span class="dl">"</span><span class="s2">Increment</span><span class="dl">"</span> <span class="p">})}</span><span class="o">&gt;</span><span class="nx">Increment</span><span class="o">&lt;</span><span class="sr">/button</span><span class="err">&gt;
</span>      <span class="o">&lt;</span><span class="nx">button</span> <span class="nx">onClick</span><span class="o">=</span><span class="p">{()</span> <span class="o">=&gt;</span> <span class="nx">dispatch</span><span class="p">({</span> <span class="na">kind</span><span class="p">:</span> <span class="dl">"</span><span class="s2">Decrement</span><span class="dl">"</span> <span class="p">})}</span><span class="o">&gt;</span><span class="nx">Decrement</span><span class="o">&lt;</span><span class="sr">/button</span><span class="err">&gt;
</span>      <span class="o">&lt;</span><span class="nx">button</span> <span class="nx">onClick</span><span class="o">=</span><span class="p">{()</span> <span class="o">=&gt;</span> <span class="nx">dispatch</span><span class="p">({</span> <span class="na">kind</span><span class="p">:</span> <span class="dl">"</span><span class="s2">Reset</span><span class="dl">"</span> <span class="p">})}</span><span class="o">&gt;</span><span class="nx">Reset</span><span class="o">&lt;</span><span class="sr">/button</span><span class="err">&gt;
</span>    <span class="o">&lt;</span><span class="sr">/div</span><span class="err">&gt;
</span>  <span class="p">);</span>
<span class="p">};</span>
</pre></td></tr></tbody></table></code></pre></div></div>

<p>We can see that we provided all the functionalities from a single props <code class="language-plaintext highlighter-rouge">dispatch</code>.</p>

<div class="language-ts highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
</pre></td><td class="rouge-code"><pre><span class="kd">const</span> <span class="nx">App</span><span class="p">:</span> <span class="nx">FC</span> <span class="o">=</span> <span class="p">()</span> <span class="o">=&gt;</span> <span class="p">{</span>
  <span class="kd">const</span> <span class="nx">initialState</span> <span class="o">=</span> <span class="p">{</span>
    <span class="na">count</span><span class="p">:</span> <span class="mi">0</span><span class="p">,</span>
  <span class="p">};</span>

  <span class="kd">const</span> <span class="p">[</span><span class="nx">state</span><span class="p">,</span> <span class="nx">dispatch</span><span class="p">]</span> <span class="o">=</span> <span class="nx">useReducer</span><span class="p">(</span><span class="nx">reducer</span><span class="p">,</span> <span class="nx">initialState</span><span class="p">);</span>

  <span class="k">return</span> <span class="p">(</span>
    <span class="o">&lt;&gt;</span>
      <span class="o">&lt;</span><span class="nx">ButtonComponent</span> <span class="nx">dispatch</span><span class="o">=</span><span class="p">{</span><span class="nx">dispatch</span><span class="p">}</span><span class="o">&gt;&lt;</span><span class="sr">/ButtonComponent</span><span class="err">&gt;
</span>      <span class="o">&lt;</span><span class="nx">p</span><span class="o">&gt;</span><span class="p">{</span><span class="nx">state</span><span class="p">.</span><span class="nx">count</span><span class="p">}</span><span class="o">&lt;</span><span class="sr">/p</span><span class="err">&gt;
</span>    <span class="o">&lt;</span><span class="sr">/</span><span class="err">&gt;
</span>  <span class="p">);</span>
<span class="p">};</span>
</pre></td></tr></tbody></table></code></pre></div></div>

<p>We can go even a step further if we want to globally provide the dispatcher to all children, we can provide it in a context:</p>

<div class="language-ts highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
</pre></td><td class="rouge-code"><pre><span class="kd">const</span> <span class="nx">DispatcherContext</span> <span class="o">=</span> <span class="nx">React</span><span class="p">.</span><span class="nx">createContext</span><span class="o">&lt;</span>
  <span class="p">{</span> <span class="na">dispatch</span><span class="p">:</span> <span class="nx">Dispatch</span><span class="o">&lt;</span><span class="nx">CounterAction</span><span class="o">&gt;</span> <span class="p">}</span> <span class="o">|</span> <span class="kc">undefined</span>
<span class="o">&gt;</span><span class="p">(</span><span class="kc">undefined</span><span class="p">);</span>
</pre></td></tr></tbody></table></code></pre></div></div>

<p>After defining the context we can use it in our children components:</p>

<div class="language-ts highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
</pre></td><td class="rouge-code"><pre><span class="kd">const</span> <span class="nx">ButtonComponent</span><span class="p">:</span> <span class="nx">FC</span> <span class="o">=</span> <span class="p">()</span> <span class="o">=&gt;</span> <span class="p">{</span>
  <span class="kd">const</span> <span class="nx">dispatcher</span> <span class="o">=</span> <span class="nx">useContext</span><span class="p">(</span><span class="nx">DispatcherContext</span><span class="p">);</span>

  <span class="k">return</span> <span class="p">(</span>
    <span class="o">&lt;</span><span class="nx">div</span><span class="o">&gt;</span>
      <span class="o">&lt;</span><span class="nx">button</span> <span class="nx">onClick</span><span class="o">=</span><span class="p">{()</span> <span class="o">=&gt;</span> <span class="nx">dispatcher</span><span class="p">?.</span><span class="nx">dispatch</span><span class="p">({</span> <span class="na">kind</span><span class="p">:</span> <span class="dl">"</span><span class="s2">Increment</span><span class="dl">"</span> <span class="p">})}</span><span class="o">&gt;</span>
        <span class="nx">Increment</span>
      <span class="o">&lt;</span><span class="sr">/button</span><span class="err">&gt;
</span>      <span class="o">&lt;</span><span class="nx">button</span> <span class="nx">onClick</span><span class="o">=</span><span class="p">{()</span> <span class="o">=&gt;</span> <span class="nx">dispatcher</span><span class="p">?.</span><span class="nx">dispatch</span><span class="p">({</span> <span class="na">kind</span><span class="p">:</span> <span class="dl">"</span><span class="s2">Decrement</span><span class="dl">"</span> <span class="p">})}</span><span class="o">&gt;</span>
        <span class="nx">Decrement</span>
      <span class="o">&lt;</span><span class="sr">/button</span><span class="err">&gt;
</span>      <span class="o">&lt;</span><span class="nx">button</span> <span class="nx">onClick</span><span class="o">=</span><span class="p">{()</span> <span class="o">=&gt;</span> <span class="nx">dispatcher</span><span class="p">?.</span><span class="nx">dispatch</span><span class="p">({</span> <span class="na">kind</span><span class="p">:</span> <span class="dl">"</span><span class="s2">Reset</span><span class="dl">"</span> <span class="p">})}</span><span class="o">&gt;</span>
        <span class="nx">Reset</span>
      <span class="o">&lt;</span><span class="sr">/button</span><span class="err">&gt;
</span>    <span class="o">&lt;</span><span class="sr">/div</span><span class="err">&gt;
</span>  <span class="p">);</span>
<span class="p">};</span>
</pre></td></tr></tbody></table></code></pre></div></div>

<p>We can see that we no longer need to pass the <code class="language-plaintext highlighter-rouge">dispatch</code> function down and instead we can get it from the context using the <code class="language-plaintext highlighter-rouge">useContext</code> hook.</p>

<p>And lastly we provider it from the parent component:</p>

<div class="language-ts highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
</pre></td><td class="rouge-code"><pre><span class="kd">const</span> <span class="nx">App</span><span class="p">:</span> <span class="nx">FC</span> <span class="o">=</span> <span class="p">()</span> <span class="o">=&gt;</span> <span class="p">{</span>
  <span class="kd">const</span> <span class="nx">initialState</span> <span class="o">=</span> <span class="p">{</span>
    <span class="na">count</span><span class="p">:</span> <span class="mi">0</span><span class="p">,</span>
  <span class="p">};</span>

  <span class="kd">const</span> <span class="p">[</span><span class="nx">state</span><span class="p">,</span> <span class="nx">dispatch</span><span class="p">]</span> <span class="o">=</span> <span class="nx">useReducer</span><span class="p">(</span><span class="nx">reducer</span><span class="p">,</span> <span class="nx">initialState</span><span class="p">);</span>

  <span class="k">return</span> <span class="p">(</span>
    <span class="o">&lt;</span><span class="nx">DispatcherContext</span><span class="p">.</span><span class="nx">Provider</span> <span class="nx">value</span><span class="o">=&gt;</span>
      <span class="o">&lt;</span><span class="nx">ButtonComponent</span><span class="o">&gt;&lt;</span><span class="sr">/ButtonComponent</span><span class="err">&gt;
</span>      <span class="o">&lt;</span><span class="nx">p</span><span class="o">&gt;</span><span class="p">{</span><span class="nx">state</span><span class="p">.</span><span class="nx">count</span><span class="p">}</span><span class="o">&lt;</span><span class="sr">/p</span><span class="err">&gt;
</span>    <span class="o">&lt;</span><span class="sr">/DispatcherContext.Provider</span><span class="err">&gt;
</span>  <span class="p">);</span>
<span class="p">};</span>
</pre></td></tr></tbody></table></code></pre></div></div>

<p>And that concludes today’s post!</p>

<h2 id="conclusion">Conclusion</h2>

<p>Today we looked at how to use <code class="language-plaintext highlighter-rouge">useReducer</code> hook to implement state management in a Redux manner in React. We started by looking at how to use the hook, we then moved on to look at the different options we had to provide functionality of the parent state to child components. I hope you liked this post and I’ll see you on the next one!</p>

<h2 id="external-sources">External Sources</h2>

<ul>
  <li><a href="https://reactjs.org/docs/hooks-reference.html">Hook Documentation</a></li>
</ul>]]></content><author><name>kimserey</name></author><category term="react" /><category term="typescript" /><summary type="html"><![CDATA[useReducer hook in React allows us to manage state in a redux manner. This is useful for handling complex state in a single object, as opposed to useState which is better used with single variable state. With useReducer, we can define a reducer, a set of actions to interact with the state and use a dispatcher to dispatch the actions from our component. In today’s post we will look at how we can use useReducer with example.]]></summary></entry><entry><title type="html">React Memo Hook</title><link href="https://kimserey.lam.gitlab.io/react/typescript/2022/04/08/react-memo-hook.html" rel="alternate" type="text/html" title="React Memo Hook" /><published>2022-04-08T00:00:00-05:00</published><updated>2022-04-08T00:00:00-05:00</updated><id>https://kimserey.lam.gitlab.io/react/typescript/2022/04/08/react-memo-hook</id><content type="html" xml:base="https://kimserey.lam.gitlab.io/react/typescript/2022/04/08/react-memo-hook.html"><![CDATA[<p><code class="language-plaintext highlighter-rouge">useMemo</code> hook in React can be used to memoize values. Memoization is used as an optimization by caching previous result of computation and directly returning the result when teh same inputs are requested. In today’s post, we’ll look at how we can use <code class="language-plaintext highlighter-rouge">useMemo</code>.</p>

<!--more-->

<ul>
  <li><a href="#usememo-hook"><code class="language-plaintext highlighter-rouge">useMemo</code> Hook</a></li>
</ul>

<h2 id="usememo-hook"><a href="#usememo-hook"><code class="language-plaintext highlighter-rouge">useMemo</code> Hook</a></h2>

<p>Understanding memo with an example is straight forward:</p>

<div class="language-ts highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
</pre></td><td class="rouge-code"><pre><span class="kd">const</span> <span class="nx">MyComponent</span><span class="p">:</span> <span class="nx">FC</span><span class="o">&lt;</span><span class="p">{</span> <span class="na">msg</span><span class="p">:</span> <span class="kr">string</span> <span class="p">}</span><span class="o">&gt;</span> <span class="o">=</span> <span class="p">({</span> <span class="nx">msg</span> <span class="p">})</span> <span class="o">=&gt;</span> <span class="p">{</span>
  <span class="kd">const</span> <span class="nx">appendTest</span> <span class="o">=</span> <span class="p">(</span><span class="na">message</span><span class="p">:</span> <span class="kr">string</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
    <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">called</span><span class="dl">"</span><span class="p">);</span>
    <span class="k">return</span> <span class="nx">message</span> <span class="o">+</span> <span class="dl">"</span><span class="s2"> test</span><span class="dl">"</span><span class="p">;</span>
  <span class="p">};</span>

  <span class="kd">const</span> <span class="nx">value</span> <span class="o">=</span> <span class="nx">appendTest</span><span class="p">(</span><span class="nx">msg</span><span class="p">);</span>

  <span class="k">return</span> <span class="o">&lt;&gt;</span><span class="p">{</span><span class="nx">value</span><span class="p">}</span><span class="o">&lt;</span><span class="sr">/&gt;</span><span class="err">;
</span><span class="p">};</span>
</pre></td></tr></tbody></table></code></pre></div></div>

<p>We have a component accepting a prop <code class="language-plaintext highlighter-rouge">msg</code>, which internally has a function declared which gets called within the body of our function component. The fact that it is defined and called within the body makes it such that at every render, the function <code class="language-plaintext highlighter-rouge">appendTest</code> will be called, regardless of whether <code class="language-plaintext highlighter-rouge">msg</code> has changed or not.</p>

<p>We can see that by checking the console log where we print <code class="language-plaintext highlighter-rouge">"called"</code>.</p>

<p>To optimize those calls, we can wrap the call to <code class="language-plaintext highlighter-rouge">appendTest</code> into <code class="language-plaintext highlighter-rouge">useMemo</code>:</p>

<div class="language-ts highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
</pre></td><td class="rouge-code"><pre><span class="kd">const</span> <span class="nx">value</span> <span class="o">=</span> <span class="nx">useMemo</span><span class="p">(()</span> <span class="o">=&gt;</span> <span class="nx">appendTest</span><span class="p">(</span><span class="nx">msg</span><span class="p">),</span> <span class="p">[</span><span class="nx">msg</span><span class="p">]);</span>
</pre></td></tr></tbody></table></code></pre></div></div>

<p>The second argument is an array which identify the dependencies on which the memoized function will be reexecuted. It’s important to have that array right as it can lead to bugs where the result is still based on passed values. It is recommended to use the <code class="language-plaintext highlighter-rouge">exhaustive-deps</code> rule to make sure we don’t forget any dependencies.</p>

<p>The dependency would include whatever argument is passed to <code class="language-plaintext highlighter-rouge">appendTest</code> but also any dependency referenced within <code class="language-plaintext highlighter-rouge">appendTest</code>.</p>

<p>Here is a full example:</p>

<div class="language-ts highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
</pre></td><td class="rouge-code"><pre><span class="kd">const</span> <span class="nx">MyComponent</span><span class="p">:</span> <span class="nx">FC</span><span class="o">&lt;</span><span class="p">{</span> <span class="na">msg</span><span class="p">:</span> <span class="kr">string</span> <span class="p">}</span><span class="o">&gt;</span> <span class="o">=</span> <span class="p">({</span> <span class="nx">msg</span> <span class="p">})</span> <span class="o">=&gt;</span> <span class="p">{</span>
  <span class="kd">const</span> <span class="nx">appendTest</span> <span class="o">=</span> <span class="p">(</span><span class="na">message</span><span class="p">:</span> <span class="kr">string</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
    <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">called</span><span class="dl">"</span><span class="p">);</span>
    <span class="k">return</span> <span class="nx">message</span> <span class="o">+</span> <span class="dl">"</span><span class="s2"> test</span><span class="dl">"</span><span class="p">;</span>
  <span class="p">};</span>

  <span class="kd">const</span> <span class="nx">value</span> <span class="o">=</span> <span class="nx">useMemo</span><span class="p">(()</span> <span class="o">=&gt;</span> <span class="nx">appendTest</span><span class="p">(</span><span class="nx">msg</span><span class="p">),</span> <span class="p">[</span><span class="nx">msg</span><span class="p">]);</span>

  <span class="k">return</span> <span class="o">&lt;&gt;</span><span class="p">{</span><span class="nx">value</span><span class="p">}</span><span class="o">&lt;</span><span class="sr">/&gt;</span><span class="err">;
</span><span class="p">};</span>

<span class="kd">const</span> <span class="nx">App</span><span class="p">:</span> <span class="nx">FC</span> <span class="o">=</span> <span class="p">()</span> <span class="o">=&gt;</span> <span class="p">{</span>
  <span class="kd">const</span> <span class="p">[</span><span class="nx">state</span><span class="p">,</span> <span class="nx">setState</span><span class="p">]</span> <span class="o">=</span> <span class="nx">useState</span><span class="p">(</span><span class="dl">""</span><span class="p">);</span>
  <span class="kd">const</span> <span class="p">[</span><span class="nx">date</span><span class="p">,</span> <span class="nx">setDate</span><span class="p">]</span> <span class="o">=</span> <span class="nx">useState</span><span class="p">(</span><span class="k">new</span> <span class="nb">Date</span><span class="p">().</span><span class="nx">toISOString</span><span class="p">());</span>

  <span class="nx">useEffect</span><span class="p">(()</span> <span class="o">=&gt;</span> <span class="p">{</span>
    <span class="kd">const</span> <span class="nx">interval</span> <span class="o">=</span> <span class="nx">setInterval</span><span class="p">(()</span> <span class="o">=&gt;</span> <span class="p">{</span>
      <span class="nx">setDate</span><span class="p">(</span><span class="k">new</span> <span class="nb">Date</span><span class="p">().</span><span class="nx">toISOString</span><span class="p">());</span>
    <span class="p">},</span> <span class="mi">1000</span><span class="p">);</span>

    <span class="k">return</span> <span class="p">()</span> <span class="o">=&gt;</span> <span class="nx">clearInterval</span><span class="p">(</span><span class="nx">interval</span><span class="p">);</span>
  <span class="p">},</span> <span class="p">[]);</span>

  <span class="k">return</span> <span class="p">(</span>
    <span class="o">&lt;&gt;</span>
      <span class="o">&lt;</span><span class="nx">button</span> <span class="nx">onClick</span><span class="o">=</span><span class="p">{()</span> <span class="o">=&gt;</span> <span class="nx">setState</span><span class="p">(</span><span class="k">new</span> <span class="nb">Date</span><span class="p">().</span><span class="nx">toISOString</span><span class="p">())}</span><span class="o">&gt;</span><span class="nx">Click</span><span class="o">&lt;</span><span class="sr">/button</span><span class="err">&gt;
</span>      <span class="o">&lt;</span><span class="nx">MyComponent</span> <span class="nx">msg</span><span class="o">=</span><span class="p">{</span><span class="nx">state</span><span class="p">}</span><span class="o">&gt;&lt;</span><span class="sr">/MyComponent</span><span class="err">&gt;
</span>      <span class="o">&lt;</span><span class="nx">p</span><span class="o">&gt;</span><span class="p">{</span><span class="nx">date</span><span class="p">}</span><span class="o">&lt;</span><span class="sr">/p</span><span class="err">&gt;
</span>    <span class="o">&lt;</span><span class="sr">/</span><span class="err">&gt;
</span>  <span class="p">);</span>
<span class="p">};</span>
</pre></td></tr></tbody></table></code></pre></div></div>

<p>By running this example we can see that the memo is caching the result of <code class="language-plaintext highlighter-rouge">appendTest</code> as even thought <code class="language-plaintext highlighter-rouge">MyComponent</code> is being rendered at every change of our <code class="language-plaintext highlighter-rouge">date</code> state, the call to <code class="language-plaintext highlighter-rouge">appendTest</code> only happens when we click the button.</p>

<p>And that concludes today’s post!</p>

<h2 id="conclusion">Conclusion</h2>

<p>Today we looked at <code class="language-plaintext highlighter-rouge">useMemo</code> hook. We started by explaining what the purpose of memoization was, and then moved on to using the hook in our example seeing how it changes the behaviour of the code. Hope you liked this post and I’ll see you on the next one!</p>

<h2 id="external-sources">External Sources</h2>

<ul>
  <li><a href="https://reactjs.org/docs/hooks-reference.html#usememo">Memo Hook Documentation</a></li>
</ul>]]></content><author><name>kimserey</name></author><category term="react" /><category term="typescript" /><summary type="html"><![CDATA[useMemo hook in React can be used to memoize values. Memoization is used as an optimization by caching previous result of computation and directly returning the result when teh same inputs are requested. In today’s post, we’ll look at how we can use useMemo.]]></summary></entry><entry><title type="html">React Callback Hook</title><link href="https://kimserey.lam.gitlab.io/react/typescript/2022/04/01/react-callback-hook.html" rel="alternate" type="text/html" title="React Callback Hook" /><published>2022-04-01T00:00:00-05:00</published><updated>2022-04-01T00:00:00-05:00</updated><id>https://kimserey.lam.gitlab.io/react/typescript/2022/04/01/react-callback-hook</id><content type="html" xml:base="https://kimserey.lam.gitlab.io/react/typescript/2022/04/01/react-callback-hook.html"><![CDATA[<p><code class="language-plaintext highlighter-rouge">Callback</code> hook in React can be used to memoized a callback function to skip unnecessary rendering. In today’s post we will see why we would <code class="language-plaintext highlighter-rouge">useCallback</code> hook.</p>

<!--more-->

<ul>
  <li><a href="#the-problem">The Problem</a></li>
  <li><a href="#usecallback-hook"><code class="language-plaintext highlighter-rouge">useCallback</code> Hook</a></li>
</ul>

<h2 id="the-problem"><a href="#the-problem">The Problem</a></h2>

<p>To understand what <code class="language-plaintext highlighter-rouge">useCallback</code> does, we start by creating a child component:</p>

<div class="language-ts highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
</pre></td><td class="rouge-code"><pre><span class="kd">const</span> <span class="nx">MyChildComponent</span><span class="p">:</span> <span class="nx">React</span><span class="p">.</span><span class="nx">FC</span><span class="o">&lt;</span><span class="p">{</span> <span class="na">say</span><span class="p">:</span> <span class="p">()</span> <span class="o">=&gt;</span> <span class="kr">string</span> <span class="p">}</span><span class="o">&gt;</span> <span class="o">=</span> <span class="p">({</span> <span class="nx">say</span> <span class="p">})</span> <span class="o">=&gt;</span> <span class="p">{</span>
  <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">My child component rendered</span><span class="dl">"</span><span class="p">,</span> <span class="k">new</span> <span class="nb">Date</span><span class="p">().</span><span class="nx">toISOString</span><span class="p">());</span>
  <span class="k">return</span> <span class="o">&lt;</span><span class="nx">p</span><span class="o">&gt;</span><span class="p">{</span><span class="nx">say</span><span class="p">()}</span><span class="o">&lt;</span><span class="sr">/p&gt;</span><span class="err">;
</span><span class="p">};</span>
</pre></td></tr></tbody></table></code></pre></div></div>

<p>We have a component which takes as input a function <code class="language-plaintext highlighter-rouge">say</code> and would log on each render a message.</p>

<p>We then use this component in a main component:</p>

<div class="language-ts highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
</pre></td><td class="rouge-code"><pre><span class="kd">const</span> <span class="nx">App</span><span class="p">:</span> <span class="nx">React</span><span class="p">.</span><span class="nx">FC</span> <span class="o">=</span> <span class="p">()</span> <span class="o">=&gt;</span> <span class="p">{</span>
  <span class="kd">const</span> <span class="p">[</span><span class="nx">state</span><span class="p">,</span> <span class="nx">setState</span><span class="p">]</span> <span class="o">=</span> <span class="nx">useState</span><span class="p">(</span><span class="kc">true</span><span class="p">);</span>

  <span class="kd">const</span> <span class="nx">say</span> <span class="o">=</span> <span class="p">()</span> <span class="o">=&gt;</span> <span class="p">{</span>
    <span class="k">return</span> <span class="nx">state</span> <span class="p">?</span> <span class="dl">"</span><span class="s2">Hello</span><span class="dl">"</span> <span class="p">:</span> <span class="dl">"</span><span class="s2">Bye</span><span class="dl">"</span><span class="p">;</span>
  <span class="p">};</span>

  <span class="k">return</span> <span class="p">(</span>
    <span class="o">&lt;&gt;</span>
      <span class="o">&lt;</span><span class="nx">p</span><span class="o">&gt;</span><span class="p">{</span><span class="nx">state</span> <span class="p">?</span> <span class="dl">"</span><span class="s2">Hello</span><span class="dl">"</span> <span class="p">:</span> <span class="dl">"</span><span class="s2">Bye</span><span class="dl">"</span><span class="p">}</span><span class="o">&lt;</span><span class="sr">/p</span><span class="err">&gt;
</span>      <span class="o">&lt;</span><span class="nx">button</span> <span class="nx">onClick</span><span class="o">=</span><span class="p">{()</span> <span class="o">=&gt;</span> <span class="nx">setState</span><span class="p">(</span><span class="o">!</span><span class="nx">state</span><span class="p">)}</span><span class="o">&gt;</span><span class="nx">Toggle</span><span class="o">&lt;</span><span class="sr">/button</span><span class="err">&gt;
</span>      <span class="o">&lt;</span><span class="nx">MyChildComponent</span> <span class="nx">say</span><span class="o">=</span><span class="p">{</span><span class="nx">say</span><span class="p">}</span><span class="o">&gt;&lt;</span><span class="sr">/MyChildComponent</span><span class="err">&gt;
</span>    <span class="o">&lt;</span><span class="sr">/</span><span class="err">&gt;
</span>  <span class="p">);</span>
<span class="p">};</span>
</pre></td></tr></tbody></table></code></pre></div></div>

<p>As we click on the button, we can see the message printed in the console. On each click, the child component renders.</p>

<p>Now let’s add another state into <code class="language-plaintext highlighter-rouge">App</code> which would just display the current time.</p>

<div class="language-ts highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
</pre></td><td class="rouge-code"><pre><span class="kd">const</span> <span class="nx">App</span><span class="p">:</span> <span class="nx">React</span><span class="p">.</span><span class="nx">FC</span> <span class="o">=</span> <span class="p">()</span> <span class="o">=&gt;</span> <span class="p">{</span>
  <span class="kd">const</span> <span class="p">[</span><span class="nx">state</span><span class="p">,</span> <span class="nx">setState</span><span class="p">]</span> <span class="o">=</span> <span class="nx">useState</span><span class="p">(</span><span class="kc">true</span><span class="p">);</span>
  <span class="kd">const</span> <span class="p">[</span><span class="nx">otherState</span><span class="p">,</span> <span class="nx">setOtherState</span><span class="p">]</span> <span class="o">=</span> <span class="nx">useState</span><span class="p">(</span><span class="k">new</span> <span class="nb">Date</span><span class="p">().</span><span class="nx">toISOString</span><span class="p">());</span>

  <span class="kd">const</span> <span class="nx">say</span> <span class="o">=</span> <span class="p">()</span> <span class="o">=&gt;</span> <span class="p">{</span>
    <span class="k">return</span> <span class="nx">state</span> <span class="p">?</span> <span class="dl">"</span><span class="s2">Hello</span><span class="dl">"</span> <span class="p">:</span> <span class="dl">"</span><span class="s2">Bye</span><span class="dl">"</span><span class="p">;</span>
  <span class="p">};</span>

  <span class="nx">useEffect</span><span class="p">(()</span> <span class="o">=&gt;</span> <span class="p">{</span>
    <span class="kd">const</span> <span class="nx">interval</span> <span class="o">=</span> <span class="nx">setInterval</span><span class="p">(()</span> <span class="o">=&gt;</span> <span class="p">{</span>
      <span class="nx">setOtherState</span><span class="p">(</span><span class="k">new</span> <span class="nb">Date</span><span class="p">().</span><span class="nx">toISOString</span><span class="p">());</span>
    <span class="p">},</span> <span class="mi">5000</span><span class="p">);</span>

    <span class="k">return</span> <span class="p">()</span> <span class="o">=&gt;</span> <span class="nx">clearInterval</span><span class="p">(</span><span class="nx">interval</span><span class="p">);</span>
  <span class="p">},</span> <span class="p">[]);</span>

  <span class="k">return</span> <span class="p">(</span>
    <span class="o">&lt;&gt;</span>
      <span class="o">&lt;</span><span class="nx">p</span><span class="o">&gt;</span><span class="p">{</span><span class="nx">state</span> <span class="p">?</span> <span class="dl">"</span><span class="s2">Hello</span><span class="dl">"</span> <span class="p">:</span> <span class="dl">"</span><span class="s2">Bye</span><span class="dl">"</span><span class="p">}</span><span class="o">&lt;</span><span class="sr">/p</span><span class="err">&gt;
</span>      <span class="o">&lt;</span><span class="nx">p</span><span class="o">&gt;</span><span class="p">{</span><span class="nx">otherState</span><span class="p">}</span><span class="o">&lt;</span><span class="sr">/p</span><span class="err">&gt;
</span>      <span class="o">&lt;</span><span class="nx">button</span> <span class="nx">onClick</span><span class="o">=</span><span class="p">{()</span> <span class="o">=&gt;</span> <span class="nx">setState</span><span class="p">(</span><span class="o">!</span><span class="nx">state</span><span class="p">)}</span><span class="o">&gt;</span><span class="nx">Toggle</span><span class="o">&lt;</span><span class="sr">/button</span><span class="err">&gt;
</span>      <span class="o">&lt;</span><span class="nx">MyChildComponent</span> <span class="nx">say</span><span class="o">=</span><span class="p">{</span><span class="nx">say</span><span class="p">}</span><span class="o">&gt;&lt;</span><span class="sr">/MyChildComponent</span><span class="err">&gt;
</span>    <span class="o">&lt;</span><span class="sr">/</span><span class="err">&gt;
</span>  <span class="p">);</span>
<span class="p">};</span>
</pre></td></tr></tbody></table></code></pre></div></div>

<p>We added <code class="language-plaintext highlighter-rouge">otherState</code> with an interval triggering a change of <code class="language-plaintext highlighter-rouge">otherState</code> every five seconds. What we observe is that our child component still render every five seconds even though it does not depend on <code class="language-plaintext highlighter-rouge">otherState</code>.</p>

<p>In fact, it only depends on the function <code class="language-plaintext highlighter-rouge">say</code> but because the parent component is rendered again, React will trigger a render on all child components. This behaviour is the most logical behaviour and will guarantee that all components that need rendering will be up-to-date.</p>

<p>But in our case here, we are defining <code class="language-plaintext highlighter-rouge">FunctionComponent</code> (or <code class="language-plaintext highlighter-rouge">FC</code>, which is a type alias) which depend only on their props. The entire logic inside our components would only need a rendering triggered from the parent if their props change.</p>

<p>This can be solved by using <code class="language-plaintext highlighter-rouge">memo</code>:</p>

<div class="language-ts highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
</pre></td><td class="rouge-code"><pre><span class="kd">const</span> <span class="nx">MyChildComponent</span><span class="p">:</span> <span class="nx">React</span><span class="p">.</span><span class="nx">FC</span><span class="o">&lt;</span><span class="p">{</span> <span class="na">say</span><span class="p">:</span> <span class="p">()</span> <span class="o">=&gt;</span> <span class="kr">string</span> <span class="p">}</span><span class="o">&gt;</span> <span class="o">=</span> <span class="nx">memo</span><span class="p">(({</span> <span class="nx">say</span> <span class="p">})</span> <span class="o">=&gt;</span> <span class="p">{</span>
  <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">My child component rendered</span><span class="dl">"</span><span class="p">,</span> <span class="k">new</span> <span class="nb">Date</span><span class="p">().</span><span class="nx">toISOString</span><span class="p">());</span>
  <span class="k">return</span> <span class="o">&lt;</span><span class="nx">p</span><span class="o">&gt;</span><span class="p">{</span><span class="nx">say</span><span class="p">()}</span><span class="o">&lt;</span><span class="sr">/p&gt;</span><span class="err">;
</span><span class="p">});</span>
</pre></td></tr></tbody></table></code></pre></div></div>

<p>We simply wrap our function component into <code class="language-plaintext highlighter-rouge">memo(...)</code> which would provide a performance boost by memoizing the result of the function component and return it to the parent for renders that don’t include any props change for that component.</p>

<p>And we finally come to the problem:</p>

<p>After wrapping with <code class="language-plaintext highlighter-rouge">memo</code>, we can see that the child component is still rendered on each change of <code class="language-plaintext highlighter-rouge">otherState</code>. The reason for that is that each functions and variables within the parent component <code class="language-plaintext highlighter-rouge">App</code> are recreated at each render, and because functions equality is treated as reference equality, the previous <code class="language-plaintext highlighter-rouge">say</code> will never be the same as the next <code class="language-plaintext highlighter-rouge">say</code> function.</p>

<p>Now that we understand the problem, we can see how <code class="language-plaintext highlighter-rouge">useCallback</code> solves it.</p>

<h2 id="usecallback-hook"><a href="#usecallback-hook"><code class="language-plaintext highlighter-rouge">useCallback</code> Hook</a></h2>

<p><code class="language-plaintext highlighter-rouge">useCallback</code> can be used to create a value holding a reference to same function on each render:</p>

<div class="language-ts highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
</pre></td><td class="rouge-code"><pre><span class="kd">const</span> <span class="nx">say</span> <span class="o">=</span> <span class="nx">useCallback</span><span class="p">(()</span> <span class="o">=&gt;</span> <span class="p">{</span>
  <span class="k">return</span> <span class="nx">state</span> <span class="p">?</span> <span class="dl">"</span><span class="s2">Hello</span><span class="dl">"</span> <span class="p">:</span> <span class="dl">"</span><span class="s2">Bye</span><span class="dl">"</span><span class="p">;</span>
<span class="p">},</span> <span class="p">[</span><span class="nx">state</span><span class="p">]);</span>
</pre></td></tr></tbody></table></code></pre></div></div>

<p>We wrap our function into <code class="language-plaintext highlighter-rouge">useCallback</code>, making sure to provide the dependency for when the function would be reevaluated. We end up with the following component:</p>

<div class="language-ts highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
</pre></td><td class="rouge-code"><pre><span class="kd">const</span> <span class="nx">App</span><span class="p">:</span> <span class="nx">React</span><span class="p">.</span><span class="nx">FC</span> <span class="o">=</span> <span class="p">()</span> <span class="o">=&gt;</span> <span class="p">{</span>
  <span class="kd">const</span> <span class="p">[</span><span class="nx">state</span><span class="p">,</span> <span class="nx">setState</span><span class="p">]</span> <span class="o">=</span> <span class="nx">useState</span><span class="p">(</span><span class="kc">true</span><span class="p">);</span>
  <span class="kd">const</span> <span class="p">[</span><span class="nx">otherState</span><span class="p">,</span> <span class="nx">setOtherState</span><span class="p">]</span> <span class="o">=</span> <span class="nx">useState</span><span class="p">(</span><span class="k">new</span> <span class="nb">Date</span><span class="p">().</span><span class="nx">toISOString</span><span class="p">());</span>

  <span class="kd">const</span> <span class="nx">say</span> <span class="o">=</span> <span class="nx">useCallback</span><span class="p">(()</span> <span class="o">=&gt;</span> <span class="p">{</span>
    <span class="k">return</span> <span class="nx">state</span> <span class="p">?</span> <span class="dl">"</span><span class="s2">Hello</span><span class="dl">"</span> <span class="p">:</span> <span class="dl">"</span><span class="s2">Bye</span><span class="dl">"</span><span class="p">;</span>
  <span class="p">},</span> <span class="p">[</span><span class="nx">state</span><span class="p">]);</span>

  <span class="nx">useEffect</span><span class="p">(()</span> <span class="o">=&gt;</span> <span class="p">{</span>
    <span class="kd">const</span> <span class="nx">interval</span> <span class="o">=</span> <span class="nx">setInterval</span><span class="p">(()</span> <span class="o">=&gt;</span> <span class="p">{</span>
      <span class="nx">setOtherState</span><span class="p">(</span><span class="k">new</span> <span class="nb">Date</span><span class="p">().</span><span class="nx">toISOString</span><span class="p">());</span>
    <span class="p">},</span> <span class="mi">5000</span><span class="p">);</span>

    <span class="k">return</span> <span class="p">()</span> <span class="o">=&gt;</span> <span class="nx">clearInterval</span><span class="p">(</span><span class="nx">interval</span><span class="p">);</span>
  <span class="p">},</span> <span class="p">[]);</span>

  <span class="k">return</span> <span class="p">(</span>
    <span class="o">&lt;&gt;</span>
      <span class="o">&lt;</span><span class="nx">p</span><span class="o">&gt;</span><span class="p">{</span><span class="nx">state</span> <span class="p">?</span> <span class="dl">"</span><span class="s2">Hello</span><span class="dl">"</span> <span class="p">:</span> <span class="dl">"</span><span class="s2">Bye</span><span class="dl">"</span><span class="p">}</span><span class="o">&lt;</span><span class="sr">/p</span><span class="err">&gt;
</span>      <span class="o">&lt;</span><span class="nx">p</span><span class="o">&gt;</span><span class="p">{</span><span class="nx">otherState</span><span class="p">}</span><span class="o">&lt;</span><span class="sr">/p</span><span class="err">&gt;
</span>      <span class="o">&lt;</span><span class="nx">button</span> <span class="nx">onClick</span><span class="o">=</span><span class="p">{()</span> <span class="o">=&gt;</span> <span class="nx">setState</span><span class="p">(</span><span class="o">!</span><span class="nx">state</span><span class="p">)}</span><span class="o">&gt;</span><span class="nx">Toggle</span><span class="o">&lt;</span><span class="sr">/button</span><span class="err">&gt;
</span>      <span class="o">&lt;</span><span class="nx">MyChildComponent</span> <span class="nx">say</span><span class="o">=</span><span class="p">{</span><span class="nx">say</span><span class="p">}</span><span class="o">&gt;&lt;</span><span class="sr">/MyChildComponent</span><span class="err">&gt;
</span>    <span class="o">&lt;</span><span class="sr">/</span><span class="err">&gt;
</span>  <span class="p">);</span>
<span class="p">};</span>
</pre></td></tr></tbody></table></code></pre></div></div>

<p>With the callback defined, we can then see that the child component is no longer rendered. This is thanks to the fact that the reference to <code class="language-plaintext highlighter-rouge">say</code> remains the same unless <code class="language-plaintext highlighter-rouge">state</code> is being updated.</p>

<p>The second argument of <code class="language-plaintext highlighter-rouge">useCallback</code> is crucial as it defines the dependencies in which the callback gets updated. If we forget to add <code class="language-plaintext highlighter-rouge">state</code> in it, we would have <code class="language-plaintext highlighter-rouge">state</code> always equal to its initial value. It’s recommended to enable <code class="language-plaintext highlighter-rouge">exhaustive-deps</code> when using <code class="language-plaintext highlighter-rouge">useCallback</code> as it prevents this sort of bugs.</p>

<p>And that concludes today’s post!</p>

<h2 id="conclusion">Conclusion</h2>

<p>In today’s post we looked at the problem that <code class="language-plaintext highlighter-rouge">useCallback</code> solves. We started by exposing the problem and then showed how we would solve it. I hope you liked this post and I’ll see you on the next one!</p>

<h2 id="external-sources">External Sources</h2>

<ul>
  <li><a href="https://reactjs.org/docs/hooks-reference.html#usecallback">Use Callback Hook</a></li>
  <li><a href="https://reactjs.org/docs/react-api.html#reactmemo">React Memo</a></li>
</ul>]]></content><author><name>kimserey</name></author><category term="react" /><category term="typescript" /><summary type="html"><![CDATA[Callback hook in React can be used to memoized a callback function to skip unnecessary rendering. In today’s post we will see why we would useCallback hook.]]></summary></entry><entry><title type="html">React Ref Hook</title><link href="https://kimserey.lam.gitlab.io/react/typescript/2022/03/25/react-ref-hook.html" rel="alternate" type="text/html" title="React Ref Hook" /><published>2022-03-25T00:00:00-05:00</published><updated>2022-03-25T00:00:00-05:00</updated><id>https://kimserey.lam.gitlab.io/react/typescript/2022/03/25/react-ref-hook</id><content type="html" xml:base="https://kimserey.lam.gitlab.io/react/typescript/2022/03/25/react-ref-hook.html"><![CDATA[<p><code class="language-plaintext highlighter-rouge">Ref</code> hook in React can be used to keep a mutable reference across multiple renders. In today’s post we will see how we can use <code class="language-plaintext highlighter-rouge">useRef</code> hook and when they are useful.</p>

<!--more-->

<ul>
  <li><a href="#useref-hook"><code class="language-plaintext highlighter-rouge">useRef</code> Hook</a></li>
  <li><a href="#gotcha">Gotcha</a></li>
</ul>

<h2 id="useref-hook"><a href="#useref-hook"><code class="language-plaintext highlighter-rouge">useRef</code> Hook</a></h2>

<p>A <code class="language-plaintext highlighter-rouge">Ref</code> is a reference to a mutable variable which is independent from the rendering. The object returned is a reference to a variable which will live for the full lifetime of the component.</p>

<p>We can create ref using <code class="language-plaintext highlighter-rouge">useRef</code>:</p>

<div class="language-ts highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
</pre></td><td class="rouge-code"><pre><span class="kd">const</span> <span class="nx">nameRef</span> <span class="o">=</span> <span class="nx">useRef</span><span class="o">&lt;</span><span class="kr">string</span><span class="o">&gt;</span><span class="p">(</span><span class="dl">"</span><span class="s2">tom</span><span class="dl">"</span><span class="p">);</span>
</pre></td></tr></tbody></table></code></pre></div></div>

<p>Then we can reference the variable directly with <code class="language-plaintext highlighter-rouge">.current</code>:</p>

<div class="language-ts highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
</pre></td><td class="rouge-code"><pre><span class="nx">cosnole</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">nameRef</span><span class="p">.</span><span class="nx">current</span><span class="p">);</span>
</pre></td></tr></tbody></table></code></pre></div></div>

<p>A common usecase in React is to use ref to reference a DOM element, for example setting the focus on a input when a component is first displayed:</p>

<div class="language-ts highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
</pre></td><td class="rouge-code"><pre><span class="kd">const</span> <span class="nx">TextInputWithFocusButton</span><span class="p">:</span> <span class="nx">React</span><span class="p">.</span><span class="nx">FC</span> <span class="o">=</span> <span class="p">()</span> <span class="o">=&gt;</span> <span class="p">{</span>
  <span class="kd">const</span> <span class="nx">inputEl</span> <span class="o">=</span> <span class="nx">useRef</span><span class="o">&lt;</span><span class="kr">any</span><span class="o">&gt;</span><span class="p">(</span><span class="kc">null</span><span class="p">);</span>

  <span class="kd">const</span> <span class="nx">focusOnInput</span> <span class="o">=</span> <span class="p">()</span> <span class="o">=&gt;</span> <span class="p">{</span>
    <span class="k">if</span> <span class="p">(</span><span class="nx">inputEl</span><span class="p">.</span><span class="nx">current</span><span class="p">)</span> <span class="p">{</span>
      <span class="nx">inputEl</span><span class="p">.</span><span class="nx">current</span><span class="p">.</span><span class="nx">focus</span><span class="p">();</span>
    <span class="p">}</span>
  <span class="p">};</span>

  <span class="nx">useEffect</span><span class="p">(()</span> <span class="o">=&gt;</span> <span class="p">{</span>
    <span class="nx">focusOnInput</span><span class="p">();</span>
  <span class="p">},</span> <span class="p">[]);</span>

  <span class="k">return</span> <span class="o">&lt;</span><span class="nx">input</span> <span class="nx">ref</span><span class="o">=</span><span class="p">{</span><span class="nx">inputEl</span><span class="p">}</span> <span class="kd">type</span><span class="o">=</span><span class="dl">"</span><span class="s2">text</span><span class="dl">"</span> <span class="o">/&gt;</span><span class="p">;</span>
<span class="p">};</span>

<span class="kd">const</span> <span class="nx">App</span><span class="p">:</span> <span class="nx">React</span><span class="p">.</span><span class="nx">FC</span> <span class="o">=</span> <span class="p">()</span> <span class="o">=&gt;</span> <span class="p">{</span>
  <span class="k">return</span> <span class="o">&lt;</span><span class="nx">TextInputWithFocusButton</span><span class="o">&gt;&lt;</span><span class="sr">/TextInputWithFocusButton&gt;</span><span class="err">;
</span><span class="p">};</span>

<span class="k">export</span> <span class="k">default</span> <span class="nx">App</span><span class="p">;</span>
</pre></td></tr></tbody></table></code></pre></div></div>

<p>We can see how <code class="language-plaintext highlighter-rouge">input</code> accepts a <code class="language-plaintext highlighter-rouge">ref</code> which is set from inside to the HTML element. We can then access it through the ref.</p>

<p>More generally, a <code class="language-plaintext highlighter-rouge">ref</code> can be used to store and reference anything that needs to survive render, or always be available at any point disregarding the render cycle. States are also persisted across render but the difference being that a state change will trigger a render while <code class="language-plaintext highlighter-rouge">ref</code> do not trigger render.</p>

<h2 id="gotcha"><a href="#gotcha">Gotcha</a></h2>

<p>Without <code class="language-plaintext highlighter-rouge">ref</code>, we wouldn’t be able to persist the value for example we may be tempted to create a regular variable at the top of our component:</p>

<div class="language-ts highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
</pre></td><td class="rouge-code"><pre><span class="kd">let</span> <span class="nx">nameRef</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">tom";
</span></pre></td></tr></tbody></table></code></pre></div></div>

<p>But the problem with that is that if the component re-render for any reason; a props change or state change or a parent re-render, <code class="language-plaintext highlighter-rouge">nameRef</code> will reset to <code class="language-plaintext highlighter-rouge">'tom'</code>.</p>

<p>And that concludes today’s post!</p>

<h2 id="conclusion">Conclusion</h2>

<p>In today’s post we saw how we can use <code class="language-plaintext highlighter-rouge">useRef</code> to keep a mutable variable around during the lifetime of the component. I hope you liked this post and I’ll see you on the next one!</p>]]></content><author><name>kimserey</name></author><category term="react" /><category term="typescript" /><summary type="html"><![CDATA[Ref hook in React can be used to keep a mutable reference across multiple renders. In today’s post we will see how we can use useRef hook and when they are useful.]]></summary></entry><entry><title type="html">React Context Hook</title><link href="https://kimserey.lam.gitlab.io/react/typescript/2022/03/18/react-context-hook.html" rel="alternate" type="text/html" title="React Context Hook" /><published>2022-03-18T00:00:00-05:00</published><updated>2022-03-18T00:00:00-05:00</updated><id>https://kimserey.lam.gitlab.io/react/typescript/2022/03/18/react-context-hook</id><content type="html" xml:base="https://kimserey.lam.gitlab.io/react/typescript/2022/03/18/react-context-hook.html"><![CDATA[<p>Context hook in React can be used to manage global state. In today’s post we will see how we can use <code class="language-plaintext highlighter-rouge">useContext</code> hook and how we can pair it with <code class="language-plaintext highlighter-rouge">useState</code> to provide a global state to all children components.</p>

<!--more-->

<ul>
  <li><a href="#usecontext-hook"><code class="language-plaintext highlighter-rouge">useContext</code> Hook</a></li>
  <li><a href="#use-with-usestate">Use with <code class="language-plaintext highlighter-rouge">useState</code></a></li>
</ul>

<h2 id="usecontext-hook"><a href="#usecontext-hook"><code class="language-plaintext highlighter-rouge">useContext</code> Hook</a></h2>

<p><code class="language-plaintext highlighter-rouge">useContext</code> is used together with <code class="language-plaintext highlighter-rouge">createContext</code>. We start first by creating a context with <code class="language-plaintext highlighter-rouge">createContext</code>:</p>

<div class="language-ts highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
</pre></td><td class="rouge-code"><pre><span class="kd">const</span> <span class="nx">UserContext</span> <span class="o">=</span> <span class="nx">createContext</span><span class="o">&lt;</span><span class="p">{</span> <span class="nx">username</span><span class="p">?:</span> <span class="kr">string</span> <span class="p">}</span><span class="o">&gt;</span><span class="p">({});</span>
</pre></td></tr></tbody></table></code></pre></div></div>

<p>The <code class="language-plaintext highlighter-rouge">Context</code> then can instantiate a <code class="language-plaintext highlighter-rouge">Provider</code> component to <em>provide</em> a value within our template:</p>

<div class="language-ts highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
</pre></td><td class="rouge-code"><pre><span class="kd">const</span> <span class="nx">App</span><span class="p">:</span> <span class="nx">React</span><span class="p">.</span><span class="nx">FC</span> <span class="o">=</span> <span class="p">()</span> <span class="o">=&gt;</span> <span class="p">{</span>
  <span class="k">return</span> <span class="p">(</span>
    <span class="o">&lt;</span><span class="nx">UserContext</span><span class="p">.</span><span class="nx">Provider</span> <span class="nx">value</span><span class="o">=</span><span class="p">{{</span> <span class="na">username</span><span class="p">:</span> <span class="dl">"</span><span class="s2">tom</span><span class="dl">"</span> <span class="p">}}</span><span class="o">&gt;</span>
      <span class="o">&lt;</span><span class="nx">div</span><span class="o">&gt;</span>
        <span class="o">&lt;</span><span class="nx">MyComponent</span><span class="o">&gt;&lt;</span><span class="sr">/MyComponent</span><span class="err">&gt;
</span>      <span class="o">&lt;</span><span class="sr">/div</span><span class="err">&gt;
</span>    <span class="o">&lt;</span><span class="sr">/UserContext.Provider</span><span class="err">&gt;
</span>  <span class="p">);</span>
<span class="p">};</span>
</pre></td></tr></tbody></table></code></pre></div></div>

<p>We can see how we create an instance of the provider with <code class="language-plaintext highlighter-rouge">UserContext.Provider</code> with a value.</p>

<p>Then from any child component, we will then be able to resolve the context using <code class="language-plaintext highlighter-rouge">useContext</code> hook providing the context as an argument:</p>

<div class="language-ts highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
</pre></td><td class="rouge-code"><pre><span class="kd">const</span> <span class="p">{</span> <span class="nx">username</span> <span class="p">}</span> <span class="o">=</span> <span class="nx">useContext</span><span class="p">(</span><span class="nx">UserContext</span><span class="p">);</span>
</pre></td></tr></tbody></table></code></pre></div></div>

<p>Putting it all together, we have:</p>

<ol>
  <li>a context <code class="language-plaintext highlighter-rouge">UserContext</code> created with <code class="language-plaintext highlighter-rouge">createContext</code> accessible across all components,</li>
  <li>a provider created with <code class="language-plaintext highlighter-rouge">UserContext.Provider</code> in the template at the root,</li>
  <li><code class="language-plaintext highlighter-rouge">useContext</code> hook used in any child component where we want to access the context value.</li>
</ol>

<div class="language-ts highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
</pre></td><td class="rouge-code"><pre><span class="k">import</span> <span class="nx">React</span><span class="p">,</span> <span class="p">{</span> <span class="nx">createContext</span><span class="p">,</span> <span class="nx">useContext</span> <span class="p">}</span> <span class="k">from</span> <span class="dl">"</span><span class="s2">react</span><span class="dl">"</span><span class="p">;</span>
<span class="k">import</span> <span class="dl">"</span><span class="s2">./App.css</span><span class="dl">"</span><span class="p">;</span>

<span class="kd">const</span> <span class="nx">UserContext</span> <span class="o">=</span> <span class="nx">createContext</span><span class="o">&lt;</span><span class="p">{</span> <span class="nx">username</span><span class="p">?:</span> <span class="kr">string</span> <span class="p">}</span><span class="o">&gt;</span><span class="p">({});</span>

<span class="kd">const</span> <span class="nx">MyInnerComponent</span><span class="p">:</span> <span class="nx">React</span><span class="p">.</span><span class="nx">FC</span> <span class="o">=</span> <span class="p">()</span> <span class="o">=&gt;</span> <span class="p">{</span>
  <span class="kd">const</span> <span class="p">{</span> <span class="nx">username</span> <span class="p">}</span> <span class="o">=</span> <span class="nx">useContext</span><span class="p">(</span><span class="nx">UserContext</span><span class="p">);</span>

  <span class="k">return</span> <span class="o">&lt;</span><span class="nx">p</span><span class="o">&gt;</span><span class="nx">Hello</span> <span class="p">{</span><span class="nx">username</span><span class="p">}</span><span class="o">&lt;</span><span class="sr">/p&gt;</span><span class="err">;
</span><span class="p">};</span>

<span class="kd">const</span> <span class="nx">MyComponent</span><span class="p">:</span> <span class="nx">React</span><span class="p">.</span><span class="nx">FC</span> <span class="o">=</span> <span class="p">()</span> <span class="o">=&gt;</span> <span class="p">{</span>
  <span class="kd">const</span> <span class="p">{</span> <span class="nx">username</span> <span class="p">}</span> <span class="o">=</span> <span class="nx">useContext</span><span class="p">(</span><span class="nx">UserContext</span><span class="p">);</span>

  <span class="k">return</span> <span class="p">(</span>
    <span class="o">&lt;</span><span class="nx">div</span><span class="o">&gt;</span>
      <span class="nx">Hello</span> <span class="p">{</span><span class="nx">username</span><span class="p">}</span>
      <span class="o">&lt;</span><span class="nx">p</span><span class="o">&gt;</span>
        <span class="o">&lt;</span><span class="nx">MyInnerComponent</span><span class="o">&gt;&lt;</span><span class="sr">/MyInnerComponent</span><span class="err">&gt;
</span>      <span class="o">&lt;</span><span class="sr">/p</span><span class="err">&gt;
</span>    <span class="o">&lt;</span><span class="sr">/div</span><span class="err">&gt;
</span>  <span class="p">);</span>
<span class="p">};</span>

<span class="kd">const</span> <span class="nx">App</span><span class="p">:</span> <span class="nx">React</span><span class="p">.</span><span class="nx">FC</span> <span class="o">=</span> <span class="p">()</span> <span class="o">=&gt;</span> <span class="p">{</span>
  <span class="k">return</span> <span class="p">(</span>
    <span class="o">&lt;</span><span class="nx">UserContext</span><span class="p">.</span><span class="nx">Provider</span> <span class="nx">value</span><span class="o">=</span><span class="p">{{</span> <span class="na">username</span><span class="p">:</span> <span class="dl">"</span><span class="s2">tom</span><span class="dl">"</span> <span class="p">}}</span><span class="o">&gt;</span>
      <span class="o">&lt;</span><span class="nx">div</span><span class="o">&gt;</span>
        <span class="o">&lt;</span><span class="nx">MyComponent</span><span class="o">&gt;&lt;</span><span class="sr">/MyComponent</span><span class="err">&gt;
</span>      <span class="o">&lt;</span><span class="sr">/div</span><span class="err">&gt;
</span>    <span class="o">&lt;</span><span class="sr">/UserContext.Provider</span><span class="err">&gt;
</span>  <span class="p">);</span>
<span class="p">};</span>

<span class="k">export</span> <span class="k">default</span> <span class="nx">App</span><span class="p">;</span>
</pre></td></tr></tbody></table></code></pre></div></div>

<p>We can see that from <code class="language-plaintext highlighter-rouge">MyComponent</code> we can access the context, and from <code class="language-plaintext highlighter-rouge">MyInnerComponent</code>, a child of <code class="language-plaintext highlighter-rouge">MyComponent</code>, we are also able to resolve the context. This removes the necessity of passing the <code class="language-plaintext highlighter-rouge">username</code> as a props on all components.</p>

<h2 id="use-with-usestate"><a href="#use-with-usestate">Use with <code class="language-plaintext highlighter-rouge">useState</code></a></h2>

<p>So far we’ve created a static context which was defined at the beginning. But we can also pair it with <code class="language-plaintext highlighter-rouge">useState</code> and set the value as a state value:</p>

<div class="language-ts highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
</pre></td><td class="rouge-code"><pre><span class="kd">const</span> <span class="nx">App</span><span class="p">:</span> <span class="nx">React</span><span class="p">.</span><span class="nx">FC</span> <span class="o">=</span> <span class="p">()</span> <span class="o">=&gt;</span> <span class="p">{</span>
  <span class="kd">const</span> <span class="p">[</span><span class="nx">username</span><span class="p">,</span> <span class="nx">setUsername</span><span class="p">]</span> <span class="o">=</span> <span class="nx">useState</span><span class="p">(</span><span class="dl">"</span><span class="s2">tom</span><span class="dl">"</span><span class="p">);</span>

  <span class="k">return</span> <span class="p">(</span>
    <span class="o">&lt;&gt;</span>
      <span class="o">&lt;</span><span class="nx">UserContext</span><span class="p">.</span><span class="nx">Provider</span> <span class="nx">value</span><span class="o">=</span><span class="p">{{</span> <span class="nx">username</span> <span class="p">}}</span><span class="o">&gt;</span>
        <span class="o">&lt;</span><span class="nx">div</span><span class="o">&gt;</span>
          <span class="o">&lt;</span><span class="nx">button</span> <span class="nx">onClick</span><span class="o">=</span><span class="p">{()</span> <span class="o">=&gt;</span> <span class="nx">setUsername</span><span class="p">(</span><span class="dl">"</span><span class="s2">sam</span><span class="dl">"</span><span class="p">)}</span><span class="o">&gt;</span><span class="nb">Set</span> <span class="nx">to</span> <span class="nx">Sam</span><span class="o">&lt;</span><span class="sr">/button</span><span class="err">&gt;
</span>          <span class="o">&lt;</span><span class="nx">MyComponent</span><span class="o">&gt;&lt;</span><span class="sr">/MyComponent</span><span class="err">&gt;
</span>        <span class="o">&lt;</span><span class="sr">/div</span><span class="err">&gt;
</span>      <span class="o">&lt;</span><span class="sr">/UserContext.Provider</span><span class="err">&gt;
</span>    <span class="o">&lt;</span><span class="sr">/</span><span class="err">&gt;
</span>  <span class="p">);</span>
<span class="p">};</span>
</pre></td></tr></tbody></table></code></pre></div></div>

<p>In that way, we are able to update the context and have all children components also have their context value updated. And that concludes today’s post on the context hook!</p>

<h2 id="conclusion">Conclusion</h2>

<p>Today we looked at the context hook in React. We started by looking at how we could use it and moved on to how we could pair it with the state hook to update the context on all components if the value was to change. I hope you liked this post and I’ll see you on the next one!</p>]]></content><author><name>kimserey</name></author><category term="react" /><category term="typescript" /><summary type="html"><![CDATA[Context hook in React can be used to manage global state. In today’s post we will see how we can use useContext hook and how we can pair it with useState to provide a global state to all children components.]]></summary></entry><entry><title type="html">React Effect Hook</title><link href="https://kimserey.lam.gitlab.io/react/typescript/2022/03/11/react-effect-hook.html" rel="alternate" type="text/html" title="React Effect Hook" /><published>2022-03-11T00:00:00-06:00</published><updated>2022-03-11T00:00:00-06:00</updated><id>https://kimserey.lam.gitlab.io/react/typescript/2022/03/11/react-effect-hook</id><content type="html" xml:base="https://kimserey.lam.gitlab.io/react/typescript/2022/03/11/react-effect-hook.html"><![CDATA[<p>When using React hooks, we often come across scenarios where we need to perform side effects. For that, a built-in hook is in our disposal; <code class="language-plaintext highlighter-rouge">useEffect</code>. In today’s post, we’ll look at how to use <code class="language-plaintext highlighter-rouge">useEffect</code> hook and in which context it should be used.</p>

<!--more-->

<ul>
  <li><a href="#useeffect-hook"><code class="language-plaintext highlighter-rouge">useEffect</code> Hook</a></li>
  <li><a href="#skipping-updates">Skipping Updates</a></li>
</ul>

<h2 id="useeffect-hook"><a href="#useeffect-hook"><code class="language-plaintext highlighter-rouge">useEffect</code> Hook</a></h2>

<p><code class="language-plaintext highlighter-rouge">useEffect</code> hook is used to decouple functionality from rendering of the component.</p>

<p>Let’s take the example of a component in an app:</p>

<div class="language-ts highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
</pre></td><td class="rouge-code"><pre><span class="kd">const</span> <span class="nx">Example</span><span class="p">:</span> <span class="nx">React</span><span class="p">.</span><span class="nx">FC</span><span class="o">&lt;</span><span class="p">{</span> <span class="na">count</span><span class="p">:</span> <span class="kr">number</span> <span class="p">}</span><span class="o">&gt;</span> <span class="o">=</span> <span class="p">({</span> <span class="nx">count</span> <span class="p">})</span> <span class="o">=&gt;</span> <span class="p">{</span>
  <span class="kd">const</span> <span class="p">[</span><span class="nx">localCount</span><span class="p">,</span> <span class="nx">setLocalCount</span><span class="p">]</span> <span class="o">=</span> <span class="nx">useState</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span>

  <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">""</span><span class="p">,</span> <span class="p">{</span> <span class="nx">count</span><span class="p">,</span> <span class="nx">localCount</span> <span class="p">});</span>

  <span class="k">return</span> <span class="p">(</span>
    <span class="o">&lt;</span><span class="nx">div</span><span class="o">&gt;</span>
      <span class="o">&lt;</span><span class="nx">p</span><span class="o">&gt;</span><span class="p">{</span><span class="nx">localCount</span><span class="p">}</span><span class="o">&lt;</span><span class="sr">/p</span><span class="err">&gt;
</span>      <span class="o">&lt;</span><span class="nx">button</span> <span class="nx">onClick</span><span class="o">=</span><span class="p">{()</span> <span class="o">=&gt;</span> <span class="nx">setLocalCount</span><span class="p">(</span><span class="nx">localCount</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)}</span><span class="o">&gt;</span><span class="nx">Local</span> <span class="nx">count</span><span class="o">&lt;</span><span class="sr">/button</span><span class="err">&gt;
</span>    <span class="o">&lt;</span><span class="sr">/div</span><span class="err">&gt;
</span>  <span class="p">);</span>
<span class="p">};</span>
</pre></td></tr></tbody></table></code></pre></div></div>

<p>We have an <code class="language-plaintext highlighter-rouge">Example</code> component which accepts a <code class="language-plaintext highlighter-rouge">count</code> and a state counter setting <code class="language-plaintext highlighter-rouge">localCount</code>.</p>

<p>The side effect <code class="language-plaintext highlighter-rouge">console.log</code> will print on each rendering of <code class="language-plaintext highlighter-rouge">Example</code>, if we use it as followed in our main <code class="language-plaintext highlighter-rouge">App</code>:</p>

<div class="language-ts highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
</pre></td><td class="rouge-code"><pre><span class="kd">const</span> <span class="nx">App</span><span class="p">:</span> <span class="nx">React</span><span class="p">.</span><span class="nx">FC</span> <span class="o">=</span> <span class="p">()</span> <span class="o">=&gt;</span> <span class="p">{</span>
  <span class="kd">const</span> <span class="p">[</span><span class="nx">count</span><span class="p">,</span> <span class="nx">setCount</span><span class="p">]</span> <span class="o">=</span> <span class="nx">useState</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span>

  <span class="k">return</span> <span class="p">(</span>
    <span class="o">&lt;&gt;</span>
      <span class="o">&lt;</span><span class="nx">div</span><span class="o">&gt;</span>
        <span class="o">&lt;</span><span class="nx">p</span><span class="o">&gt;</span><span class="p">{</span><span class="nx">count</span><span class="p">}</span><span class="o">&lt;</span><span class="sr">/p</span><span class="err">&gt;
</span>        <span class="o">&lt;</span><span class="nx">button</span> <span class="nx">onClick</span><span class="o">=</span><span class="p">{()</span> <span class="o">=&gt;</span> <span class="nx">setCount</span><span class="p">(</span><span class="nx">count</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)}</span><span class="o">&gt;</span><span class="nx">Count</span><span class="o">&lt;</span><span class="sr">/button</span><span class="err">&gt;
</span>      <span class="o">&lt;</span><span class="sr">/div</span><span class="err">&gt;
</span>      <span class="o">&lt;</span><span class="nx">div</span><span class="o">&gt;</span>
        <span class="o">&lt;</span><span class="nx">Example</span> <span class="nx">count</span><span class="o">=</span><span class="p">{</span><span class="nx">count</span><span class="p">}</span><span class="o">&gt;&lt;</span><span class="sr">/Example</span><span class="err">&gt;
</span>      <span class="o">&lt;</span><span class="sr">/div</span><span class="err">&gt;
</span>    <span class="o">&lt;</span><span class="sr">/</span><span class="err">&gt;
</span>  <span class="p">);</span>
<span class="p">};</span>
</pre></td></tr></tbody></table></code></pre></div></div>

<p>then the <code class="language-plaintext highlighter-rouge">console.log</code> will print on each render of <code class="language-plaintext highlighter-rouge">App</code> or each render of <code class="language-plaintext highlighter-rouge">Example</code> which would occur when the state changes.</p>

<p>To turn our side effect into <code class="language-plaintext highlighter-rouge">useEffect</code>, we simply wrap:</p>

<div class="language-ts highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
</pre></td><td class="rouge-code"><pre><span class="nx">useEffect</span><span class="p">(()</span> <span class="o">=&gt;</span> <span class="p">{</span>
  <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">""</span><span class="p">,</span> <span class="p">{</span> <span class="nx">count</span><span class="p">,</span> <span class="nx">localCount</span> <span class="p">});</span>
<span class="p">});</span>
</pre></td></tr></tbody></table></code></pre></div></div>

<p>Our component then becomes:</p>

<div class="language-ts highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
</pre></td><td class="rouge-code"><pre><span class="kd">const</span> <span class="nx">Example</span><span class="p">:</span> <span class="nx">React</span><span class="p">.</span><span class="nx">FC</span><span class="o">&lt;</span><span class="p">{</span> <span class="na">count</span><span class="p">:</span> <span class="kr">number</span> <span class="p">}</span><span class="o">&gt;</span> <span class="o">=</span> <span class="p">({</span> <span class="nx">count</span> <span class="p">})</span> <span class="o">=&gt;</span> <span class="p">{</span>
  <span class="kd">const</span> <span class="p">[</span><span class="nx">localCount</span><span class="p">,</span> <span class="nx">setLocalCount</span><span class="p">]</span> <span class="o">=</span> <span class="nx">useState</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span>

  <span class="nx">useEffect</span><span class="p">(()</span> <span class="o">=&gt;</span> <span class="p">{</span>
    <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">""</span><span class="p">,</span> <span class="p">{</span> <span class="nx">count</span><span class="p">,</span> <span class="nx">localCount</span> <span class="p">});</span>
  <span class="p">}]);</span>

  <span class="k">return</span> <span class="p">(</span>
    <span class="o">&lt;</span><span class="nx">div</span><span class="o">&gt;</span>
      <span class="o">&lt;</span><span class="nx">p</span><span class="o">&gt;</span><span class="p">{</span><span class="nx">localCount</span><span class="p">}</span><span class="o">&lt;</span><span class="sr">/p</span><span class="err">&gt;
</span>      <span class="o">&lt;</span><span class="nx">button</span> <span class="nx">onClick</span><span class="o">=</span><span class="p">{()</span> <span class="o">=&gt;</span> <span class="nx">setLocalCount</span><span class="p">(</span><span class="nx">localCount</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)}</span><span class="o">&gt;</span><span class="nx">Local</span> <span class="nx">count</span><span class="o">&lt;</span><span class="sr">/button</span><span class="err">&gt;
</span>    <span class="o">&lt;</span><span class="sr">/div</span><span class="err">&gt;
</span>  <span class="p">);</span>
<span class="p">};</span>
</pre></td></tr></tbody></table></code></pre></div></div>

<p>The function given to <code class="language-plaintext highlighter-rouge">useEffect</code> is called at each update, this is how <code class="language-plaintext highlighter-rouge">count</code> and <code class="language-plaintext highlighter-rouge">localCount</code> can have the correct value.</p>

<p>When we click on the buttons, we can see in the logs that the <code class="language-plaintext highlighter-rouge">console.log</code> get printed with the right value on each click:</p>

<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
</pre></td><td class="rouge-code"><pre><span class="o">{</span>count: 0, localCount: 0<span class="o">}</span>
<span class="o">{</span>count: 1, localCount: 0<span class="o">}</span>
<span class="o">{</span>count: 2, localCount: 0<span class="o">}</span>
<span class="o">{</span>count: 3, localCount: 0<span class="o">}</span>
<span class="o">{</span>count: 3, localCount: 1<span class="o">}</span>
<span class="o">{</span>count: 3, localCount: 2<span class="o">}</span>
</pre></td></tr></tbody></table></code></pre></div></div>

<p>With effect, we can also provide a function as return so that we can execute teardown functionalities:</p>

<div class="language-ts highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
</pre></td><td class="rouge-code"><pre><span class="nx">useEffect</span><span class="p">(()</span> <span class="o">=&gt;</span> <span class="p">{</span>
  <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">""</span><span class="p">,</span> <span class="p">{</span> <span class="nx">count</span><span class="p">,</span> <span class="nx">localCount</span> <span class="p">});</span>

  <span class="k">return</span> <span class="p">()</span> <span class="o">=&gt;</span> <span class="p">{</span>
    <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">teardown</span><span class="dl">"</span><span class="p">,</span> <span class="p">{</span> <span class="nx">count</span><span class="p">,</span> <span class="nx">localCount</span> <span class="p">});</span>
  <span class="p">};</span>
<span class="p">});</span>
</pre></td></tr></tbody></table></code></pre></div></div>

<p>then before the effect is executed, the previous instance will be teardowned.</p>

<h2 id="skipping-updates"><a href="#skipping-updates">Skipping Updates</a></h2>

<p>It may be too excessive to execute the effect on each render as when the parent gets rendered, it also trigger a render on the component, or when props update or state updates, it will trigger a render.</p>

<p>If we want to control the execution of <code class="language-plaintext highlighter-rouge">useEffect</code> we can provide a second argument array to state the dependencies of the effect and when it should be executed.</p>

<p>For example our effect depends on <code class="language-plaintext highlighter-rouge">count</code> and <code class="language-plaintext highlighter-rouge">localCount</code> so we can provide the following:</p>

<div class="language-ts highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
</pre></td><td class="rouge-code"><pre><span class="nx">useEffect</span><span class="p">(()</span> <span class="o">=&gt;</span> <span class="p">{</span>
  <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">""</span><span class="p">,</span> <span class="p">{</span> <span class="nx">count</span><span class="p">,</span> <span class="nx">localCount</span> <span class="p">});</span>

  <span class="k">return</span> <span class="p">()</span> <span class="o">=&gt;</span> <span class="p">{</span>
    <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">teardown</span><span class="dl">"</span><span class="p">,</span> <span class="p">{</span> <span class="nx">count</span><span class="p">,</span> <span class="nx">localCount</span> <span class="p">});</span>
  <span class="p">};</span>
<span class="p">},</span> <span class="p">[</span><span class="nx">count</span><span class="p">,</span> <span class="nx">localCount</span><span class="p">]);</span>
</pre></td></tr></tbody></table></code></pre></div></div>

<p>With this, the effect will run only when <code class="language-plaintext highlighter-rouge">count</code> or <code class="language-plaintext highlighter-rouge">localCount</code> are updated. We can verify the behavior as if we only use <code class="language-plaintext highlighter-rouge">[localCount]</code>, on changes of <code class="language-plaintext highlighter-rouge">count</code>, the effect will not be called.</p>

<p>On first render, the effect is ran once, so if we want to run only once, we can provide an empty array <code class="language-plaintext highlighter-rouge">[]</code>:</p>

<div class="language-ts highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
</pre></td><td class="rouge-code"><pre><span class="nx">useEffect</span><span class="p">(()</span> <span class="o">=&gt;</span> <span class="p">{</span>
  <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">""</span><span class="p">,</span> <span class="p">{</span> <span class="nx">count</span><span class="p">,</span> <span class="nx">localCount</span> <span class="p">});</span>

  <span class="k">return</span> <span class="p">()</span> <span class="o">=&gt;</span> <span class="p">{</span>
    <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">teardown</span><span class="dl">"</span><span class="p">,</span> <span class="p">{</span> <span class="nx">count</span><span class="p">,</span> <span class="nx">localCount</span> <span class="p">});</span>
  <span class="p">};</span>
<span class="p">},</span> <span class="p">[]);</span>
</pre></td></tr></tbody></table></code></pre></div></div>

<p>With this setup, the effect will run only once and never again. And if we don’t provide the second argument, the behavior is as described in the first section which is that the effect is ran on each update.</p>

<p>Lastly a special variant of <code class="language-plaintext highlighter-rouge">useState</code> and <code class="language-plaintext highlighter-rouge">useEffect</code>, if our effect depends on a state that the effect itself modifies, we would be entering an infinite loop where the state update triggers the effect; and the effect changes the state.</p>

<p>For example the following interval set in <code class="language-plaintext highlighter-rouge">useEffect</code>:</p>

<div class="language-ts highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
</pre></td><td class="rouge-code"><pre><span class="nx">useEffect</span><span class="p">(()</span> <span class="o">=&gt;</span> <span class="p">{</span>
  <span class="kd">const</span> <span class="nx">interval</span> <span class="o">=</span> <span class="nx">setInterval</span><span class="p">(()</span> <span class="o">=&gt;</span> <span class="nx">setLocalCount</span><span class="p">((</span><span class="nx">count</span> <span class="o">+</span> <span class="mi">1</span><span class="p">),</span> <span class="mi">1000</span><span class="p">);</span>

  <span class="k">return</span> <span class="p">()</span> <span class="o">=&gt;</span> <span class="nx">clearInterval</span><span class="p">(</span><span class="nx">interval</span><span class="p">);</span>
<span class="p">},</span> <span class="p">[]);</span>
</pre></td></tr></tbody></table></code></pre></div></div>

<p>This will always return <code class="language-plaintext highlighter-rouge">1</code> because <code class="language-plaintext highlighter-rouge">count</code> will always remain <code class="language-plaintext highlighter-rouge">0</code> as the effect is ran only once with <code class="language-plaintext highlighter-rouge">count = 0</code>. So every time the interval triggers, <code class="language-plaintext highlighter-rouge">count</code> will be <code class="language-plaintext highlighter-rouge">0</code>.</p>

<p>But the problem is that if we add <code class="language-plaintext highlighter-rouge">[count]</code> as dependency of the effect, then it will enter a loop where the interval will be teardown and recreated every time the interval kicks in.</p>

<p>The solution for that is the functional update form of <code class="language-plaintext highlighter-rouge">setLocalCount</code>:</p>

<div class="language-ts highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
</pre></td><td class="rouge-code"><pre><span class="nx">useEffect</span><span class="p">(()</span> <span class="o">=&gt;</span> <span class="p">{</span>
  <span class="kd">const</span> <span class="nx">interval</span> <span class="o">=</span> <span class="nx">setInterval</span><span class="p">(()</span> <span class="o">=&gt;</span> <span class="nx">setLocalCount</span><span class="p">((</span><span class="nx">c</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="nx">c</span> <span class="o">+</span> <span class="mi">1</span><span class="p">),</span> <span class="mi">1000</span><span class="p">);</span>

  <span class="k">return</span> <span class="p">()</span> <span class="o">=&gt;</span> <span class="nx">clearInterval</span><span class="p">(</span><span class="nx">interval</span><span class="p">);</span>
<span class="p">},</span> <span class="p">[]);</span>
</pre></td></tr></tbody></table></code></pre></div></div>

<p>That way, the state update is based on a previous state provided inside the function and we don’t reference external values.</p>

<p>And that concludes today’s post!</p>

<h2 id="conclusion">Conclusion</h2>

<p>Today we looked at <code class="language-plaintext highlighter-rouge">useEffect</code> hook and the different way of using it. We started by looking at when we should be using the hook and we then moved on to how to remove excessive without falling into any pitfall. I hope you liked this post and I’ll see you on the next one!</p>

<h2 id="external-sources">External Sources</h2>

<ul>
  <li><a href="https://reactjs.org/docs/hooks-effect.html">Hooks Effects Documentation</a></li>
</ul>]]></content><author><name>kimserey</name></author><category term="react" /><category term="typescript" /><summary type="html"><![CDATA[When using React hooks, we often come across scenarios where we need to perform side effects. For that, a built-in hook is in our disposal; useEffect. In today’s post, we’ll look at how to use useEffect hook and in which context it should be used.]]></summary></entry></feed>