{"componentChunkName":"component---src-templates-content-template-js","path":"/osa6/monimutkaisempi_tila_fetch_testaaminen","result":{"data":{"markdownRemark":{"html":"<div class=\"content\">\n<p>Jatketaan muistiinpanosovelluksen Zustand-version laajentamista.</p>\n<p>Sovelluskehitystä helpottaaksemme muutetaan alkutilaa siten, että siellä on jo muutama muistiinpano:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"gatsby-highlight-code-line\"><span class=\"token keyword\">const</span> initialNotes <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span></span><span class=\"gatsby-highlight-code-line\">    <span class=\"token punctuation\">{</span></span><span class=\"gatsby-highlight-code-line\">      <span class=\"token literal-property property\">id</span><span class=\"token operator\">:</span> <span class=\"token number\">1</span><span class=\"token punctuation\">,</span></span><span class=\"gatsby-highlight-code-line\">      <span class=\"token literal-property property\">content</span><span class=\"token operator\">:</span> <span class=\"token string\">'Zustand is less complex than Redux'</span><span class=\"token punctuation\">,</span></span><span class=\"gatsby-highlight-code-line\">      <span class=\"token literal-property property\">important</span><span class=\"token operator\">:</span> <span class=\"token boolean\">true</span><span class=\"token punctuation\">,</span></span><span class=\"gatsby-highlight-code-line\">    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span></span><span class=\"gatsby-highlight-code-line\">      <span class=\"token literal-property property\">id</span><span class=\"token operator\">:</span> <span class=\"token number\">2</span><span class=\"token punctuation\">,</span></span><span class=\"gatsby-highlight-code-line\">      <span class=\"token literal-property property\">content</span><span class=\"token operator\">:</span> <span class=\"token string\">'React app benefits from custom hooks'</span><span class=\"token punctuation\">,</span></span><span class=\"gatsby-highlight-code-line\">      <span class=\"token literal-property property\">important</span><span class=\"token operator\">:</span> <span class=\"token boolean\">false</span><span class=\"token punctuation\">,</span></span><span class=\"gatsby-highlight-code-line\">    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span></span><span class=\"gatsby-highlight-code-line\">      <span class=\"token literal-property property\">id</span><span class=\"token operator\">:</span> <span class=\"token number\">3</span><span class=\"token punctuation\">,</span></span><span class=\"gatsby-highlight-code-line\">      <span class=\"token literal-property property\">content</span><span class=\"token operator\">:</span> <span class=\"token string\">'Remember to sleep well'</span><span class=\"token punctuation\">,</span></span><span class=\"gatsby-highlight-code-line\">      <span class=\"token literal-property property\">important</span><span class=\"token operator\">:</span> <span class=\"token boolean\">true</span><span class=\"token punctuation\">,</span></span><span class=\"gatsby-highlight-code-line\">    <span class=\"token punctuation\">}</span></span><span class=\"gatsby-highlight-code-line\">  <span class=\"token punctuation\">]</span></span><span class=\"gatsby-highlight-code-line\"></span><span class=\"gatsby-highlight-code-line\"></span>\n<span class=\"token keyword\">const</span> useNoteStore <span class=\"token operator\">=</span> <span class=\"token function\">create</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token parameter\"><span class=\"token keyword\">set</span></span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span>\n  <span class=\"token literal-property property\">notes</span><span class=\"token operator\">:</span> initialNotes<span class=\"token punctuation\">,</span>\n  <span class=\"token comment\">// ...</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<h3>Monimutkaisempi tila</h3>\n<p>Toteutetaan sovellukseen näytettävien muistiinpanojen filtteröinti, jonka avulla näytettäviä muistiinpanoja voidaan rajata. Filtterin toteutus tapahtuu <a href=\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/radio\">radiopainikkeiden</a> avulla:</p>\n<picture><img src=\"/static/a10eaa11ed554b28b204fd0840d62e00/5a190/u1.png\" alt=\"Sivun alussa lomake muistiinpanon lisäämiseen (syötekenttä ja nappi add). Tämän jälkeen radiopainikevalinta mitkä muistiinpanot näytetään, vaihtoehdot all, important ja nonimportant. Näiden alle renderöidään kaikki muistiinpanot ja niiden yhteyteen teksti important jos muistiinpano merkattu tärkeäksi. \" srcset=\"/static/a10eaa11ed554b28b204fd0840d62e00/772e8/u1.png 200w,\n/static/a10eaa11ed554b28b204fd0840d62e00/e17e5/u1.png 400w,\n/static/a10eaa11ed554b28b204fd0840d62e00/5a190/u1.png 800w,\n/static/a10eaa11ed554b28b204fd0840d62e00/c1b63/u1.png 1200w,\n/static/a10eaa11ed554b28b204fd0840d62e00/fde66/u1.png 1574w\" sizes=\"(max-width: 800px) 100vw, 800px\"></picture>\n<p>Herää kysymys, miten filtterin tilanhallinta kannattaisi hoitaa. Vaihtoehtoja on käytännössä kaksi: tehdään filterille erillinen store Zustandilla, tai lisätään se olemasaolevaan storeen. Kumpikin näistä ratkaisuista on perusteltavissa. Internetistä löytyvät <a href=\"https://tkdodo.eu/blog/working-with-zustand#keep-the-scope-of-your-store-small\">parhaat käytänteet</a> kehottavat pitämään toisistaan täysin erilliset asiat erillisissä storeissa. Muistiinpanojen lista ja filtteröinti ovat kuitenkin sen verran sidoksissa toisiinsa, että päädymme sijoittamaan molemmat samaan storeen:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token keyword\">const</span> useNoteStore <span class=\"token operator\">=</span> <span class=\"token function\">create</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token parameter\"><span class=\"token keyword\">set</span></span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span>\n  <span class=\"token literal-property property\">notes</span><span class=\"token operator\">:</span> initialNotes<span class=\"token punctuation\">,</span>\n<span class=\"gatsby-highlight-code-line\">  <span class=\"token literal-property property\">filter</span><span class=\"token operator\">:</span> <span class=\"token string\">'all'</span><span class=\"token punctuation\">,</span></span>  <span class=\"token literal-property property\">actions</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token function-variable function\">add</span><span class=\"token operator\">:</span> <span class=\"token parameter\">note</span> <span class=\"token operator\">=></span> <span class=\"token function\">set</span><span class=\"token punctuation\">(</span>\n      <span class=\"token parameter\">state</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">notes</span><span class=\"token operator\">:</span> state<span class=\"token punctuation\">.</span>notes<span class=\"token punctuation\">.</span><span class=\"token function\">concat</span><span class=\"token punctuation\">(</span>note<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n    <span class=\"token function-variable function\">toggleImportance</span><span class=\"token operator\">:</span> <span class=\"token parameter\">id</span> <span class=\"token operator\">=></span> <span class=\"token function\">set</span><span class=\"token punctuation\">(</span>\n      <span class=\"token parameter\">state</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span>\n        <span class=\"token literal-property property\">notes</span><span class=\"token operator\">:</span> state<span class=\"token punctuation\">.</span>notes<span class=\"token punctuation\">.</span><span class=\"token function\">map</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">note</span> <span class=\"token operator\">=></span>\n          note<span class=\"token punctuation\">.</span>id <span class=\"token operator\">===</span> id <span class=\"token operator\">?</span> <span class=\"token punctuation\">{</span> <span class=\"token operator\">...</span>note<span class=\"token punctuation\">,</span> <span class=\"token literal-property property\">important</span><span class=\"token operator\">:</span> <span class=\"token operator\">!</span>note<span class=\"token punctuation\">.</span>important <span class=\"token punctuation\">}</span> <span class=\"token operator\">:</span> note\n        <span class=\"token punctuation\">)</span>\n      <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n<span class=\"gatsby-highlight-code-line\">    <span class=\"token function-variable function\">setFilter</span><span class=\"token operator\">:</span> <span class=\"token parameter\">value</span> <span class=\"token operator\">=></span> <span class=\"token function\">set</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">filter</span><span class=\"token operator\">:</span> value <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span></span>  <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n\n<span class=\"token keyword\">export</span> <span class=\"token keyword\">const</span> <span class=\"token function-variable function\">useNotes</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token function\">useNoteStore</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">state</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> state<span class=\"token punctuation\">.</span>notes<span class=\"token punctuation\">)</span>\n<span class=\"gatsby-highlight-code-line\"><span class=\"token keyword\">export</span> <span class=\"token keyword\">const</span> <span class=\"token function-variable function\">useFilter</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token function\">useNoteStore</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">state</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> state<span class=\"token punctuation\">.</span>filter<span class=\"token punctuation\">)</span></span><span class=\"token keyword\">export</span> <span class=\"token keyword\">const</span> <span class=\"token function-variable function\">useNoteActions</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token function\">useNoteStore</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">state</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> state<span class=\"token punctuation\">.</span>actions<span class=\"token punctuation\">)</span></code></pre></div>\n<p>Filtterille arvon asettava komponentti:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token keyword\">import</span> <span class=\"token punctuation\">{</span> useNoteActions <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">'./store'</span>\n\n<span class=\"token keyword\">const</span> <span class=\"token function-variable function\">VisibilityFilter</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">const</span> <span class=\"token punctuation\">{</span> setFilter <span class=\"token punctuation\">}</span> <span class=\"token operator\">=</span> <span class=\"token function\">useNoteActions</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n\n  <span class=\"token keyword\">return</span> <span class=\"token punctuation\">(</span>\n    <span class=\"token operator\">&lt;</span>div<span class=\"token operator\">></span>\n      <span class=\"token operator\">&lt;</span>input\n        type<span class=\"token operator\">=</span><span class=\"token string\">\"radio\"</span>\n        name<span class=\"token operator\">=</span><span class=\"token string\">\"filter\"</span>\n        onChange<span class=\"token operator\">=</span><span class=\"token punctuation\">{</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token function\">setFilter</span><span class=\"token punctuation\">(</span><span class=\"token string\">'all'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">}</span>\n        defaultChecked\n      <span class=\"token operator\">/</span><span class=\"token operator\">></span>\n      all\n      <span class=\"token operator\">&lt;</span>input\n        type<span class=\"token operator\">=</span><span class=\"token string\">\"radio\"</span>\n        name<span class=\"token operator\">=</span><span class=\"token string\">\"filter\"</span>\n        onChange<span class=\"token operator\">=</span><span class=\"token punctuation\">{</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token function\">setFilter</span><span class=\"token punctuation\">(</span><span class=\"token string\">'important'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">}</span>\n      <span class=\"token operator\">/</span><span class=\"token operator\">></span>\n      important\n      <span class=\"token operator\">&lt;</span>input\n        type<span class=\"token operator\">=</span><span class=\"token string\">\"radio\"</span>\n        name<span class=\"token operator\">=</span><span class=\"token string\">\"filter\"</span>\n        onChange<span class=\"token operator\">=</span><span class=\"token punctuation\">{</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token function\">setFilter</span><span class=\"token punctuation\">(</span><span class=\"token string\">'nonimportant'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">}</span>\n      <span class=\"token operator\">/</span><span class=\"token operator\">></span>\n      not important\n    <span class=\"token operator\">&lt;</span><span class=\"token operator\">/</span>div<span class=\"token operator\">></span>\n  <span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">}</span>\n\n<span class=\"token keyword\">export</span> <span class=\"token keyword\">default</span> VisibilityFilter</code></pre></div>\n<p>Komponentti <i>App</i> renderöi filtterin:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token keyword\">const</span> <span class=\"token function-variable function\">App</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">(</span>\n  <span class=\"token operator\">&lt;</span>div<span class=\"token operator\">></span>\n    <span class=\"token operator\">&lt;</span>NoteForm <span class=\"token operator\">/</span><span class=\"token operator\">></span>\n<span class=\"gatsby-highlight-code-line\">    <span class=\"token operator\">&lt;</span>VisibilityFilter <span class=\"token operator\">/</span><span class=\"token operator\">></span></span>    <span class=\"token operator\">&lt;</span>NoteList <span class=\"token operator\">/</span><span class=\"token operator\">></span>\n  <span class=\"token operator\">&lt;</span><span class=\"token operator\">/</span>div<span class=\"token operator\">></span>\n<span class=\"token punctuation\">)</span></code></pre></div>\n<p>Näytettävien muistiinpanojen filtteröinti voitaisiin hoitaa komponentissa <i>NoteList</i> esim. seuraavassa:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token keyword\">import</span> <span class=\"token punctuation\">{</span> useNotes<span class=\"token punctuation\">,</span> useFilter <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">'./store'</span>\n<span class=\"token keyword\">import</span> Note <span class=\"token keyword\">from</span> <span class=\"token string\">'./Note'</span>\n\n<span class=\"token keyword\">const</span> <span class=\"token function-variable function\">NoteList</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">const</span> notes <span class=\"token operator\">=</span> <span class=\"token function\">useNotes</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n<span class=\"gatsby-highlight-code-line\">  <span class=\"token keyword\">const</span> filter <span class=\"token operator\">=</span> <span class=\"token function\">useFilter</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></span>\n<span class=\"gatsby-highlight-code-line\">  <span class=\"token keyword\">const</span> notesToShow <span class=\"token operator\">=</span> notes<span class=\"token punctuation\">.</span><span class=\"token function\">filter</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">note</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span></span><span class=\"gatsby-highlight-code-line\">    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>filter <span class=\"token operator\">===</span> <span class=\"token string\">'important'</span><span class=\"token punctuation\">)</span> <span class=\"token keyword\">return</span> note<span class=\"token punctuation\">.</span>important</span><span class=\"gatsby-highlight-code-line\">    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>filter <span class=\"token operator\">===</span> <span class=\"token string\">'nonimportant'</span><span class=\"token punctuation\">)</span> <span class=\"token keyword\">return</span> <span class=\"token operator\">!</span>note<span class=\"token punctuation\">.</span>important</span><span class=\"gatsby-highlight-code-line\">    <span class=\"token keyword\">return</span> <span class=\"token boolean\">true</span></span><span class=\"gatsby-highlight-code-line\">  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span></span>\n  <span class=\"token keyword\">return</span> <span class=\"token punctuation\">(</span>\n    <span class=\"token operator\">&lt;</span>ul<span class=\"token operator\">></span>\n<span class=\"gatsby-highlight-code-line\">      <span class=\"token punctuation\">{</span>notesToShow<span class=\"token punctuation\">.</span><span class=\"token function\">map</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">note</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">(</span></span>        <span class=\"token operator\">&lt;</span>Note key<span class=\"token operator\">=</span><span class=\"token punctuation\">{</span>note<span class=\"token punctuation\">.</span>id<span class=\"token punctuation\">}</span> note<span class=\"token operator\">=</span><span class=\"token punctuation\">{</span>note<span class=\"token punctuation\">}</span> <span class=\"token operator\">/</span><span class=\"token operator\">></span>\n      <span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">}</span>\n    <span class=\"token operator\">&lt;</span><span class=\"token operator\">/</span>ul<span class=\"token operator\">></span>\n  <span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>Parempaan ratkaisuun päädytään jos filtteröintilogiikka sisällytetään suoraan storen funktioon <i>useNotes</i>:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token keyword\">import</span> <span class=\"token punctuation\">{</span> create <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">'zustand'</span>\n\n<span class=\"token keyword\">const</span> useNoteStore <span class=\"token operator\">=</span> <span class=\"token function\">create</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token parameter\"><span class=\"token keyword\">set</span></span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span>\n  <span class=\"token comment\">// ...</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n\n<span class=\"gatsby-highlight-code-line\"><span class=\"token keyword\">export</span> <span class=\"token keyword\">const</span> <span class=\"token function-variable function\">useNotes</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span></span><span class=\"gatsby-highlight-code-line\">  <span class=\"token keyword\">const</span> notes <span class=\"token operator\">=</span> <span class=\"token function\">useNoteStore</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">state</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> state<span class=\"token punctuation\">.</span>notes<span class=\"token punctuation\">)</span></span><span class=\"gatsby-highlight-code-line\">  <span class=\"token keyword\">const</span> filter <span class=\"token operator\">=</span> <span class=\"token function\">useNoteStore</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">state</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> state<span class=\"token punctuation\">.</span>filter<span class=\"token punctuation\">)</span></span><span class=\"gatsby-highlight-code-line\"></span><span class=\"gatsby-highlight-code-line\">  <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>filter <span class=\"token operator\">===</span> <span class=\"token string\">'important'</span><span class=\"token punctuation\">)</span> <span class=\"token keyword\">return</span> notes<span class=\"token punctuation\">.</span><span class=\"token function\">filter</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">n</span> <span class=\"token operator\">=></span> n<span class=\"token punctuation\">.</span>important<span class=\"token punctuation\">)</span></span><span class=\"gatsby-highlight-code-line\">  <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>filter <span class=\"token operator\">===</span> <span class=\"token string\">'nonimportant'</span><span class=\"token punctuation\">)</span> <span class=\"token keyword\">return</span> notes<span class=\"token punctuation\">.</span><span class=\"token function\">filter</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">n</span> <span class=\"token operator\">=></span> <span class=\"token operator\">!</span>n<span class=\"token punctuation\">.</span>important<span class=\"token punctuation\">)</span></span><span class=\"gatsby-highlight-code-line\"></span><span class=\"gatsby-highlight-code-line\">  <span class=\"token keyword\">return</span> notes</span><span class=\"gatsby-highlight-code-line\"><span class=\"token punctuation\">}</span></span></code></pre></div>\n<p>Eli funktio <i>useNotes</i> palauttaa aina halutulla tavalla filtteröidyn muistiinpanojen listan. Funktion käyttäjän, eli komponentin <i>NoteList</i> ei tarvitse edes olla tietoinen filtterin olemassaolosta:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token keyword\">import</span> <span class=\"token punctuation\">{</span> useNotes <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">'./store'</span>\n<span class=\"token keyword\">import</span> Note <span class=\"token keyword\">from</span> <span class=\"token string\">'./Note'</span>\n\n<span class=\"token keyword\">const</span> <span class=\"token function-variable function\">NoteList</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n  <span class=\"token comment\">// component gets always the properly filtered set of notes</span>\n  <span class=\"token keyword\">const</span> notes <span class=\"token operator\">=</span> <span class=\"token function\">useNotes</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n\n  <span class=\"token keyword\">return</span> <span class=\"token punctuation\">(</span>\n    <span class=\"token operator\">&lt;</span>ul<span class=\"token operator\">></span>\n      <span class=\"token punctuation\">{</span>notes<span class=\"token punctuation\">.</span><span class=\"token function\">map</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">note</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">(</span>\n        <span class=\"token operator\">&lt;</span>Note key<span class=\"token operator\">=</span><span class=\"token punctuation\">{</span>note<span class=\"token punctuation\">.</span>id<span class=\"token punctuation\">}</span> note<span class=\"token operator\">=</span><span class=\"token punctuation\">{</span>note<span class=\"token punctuation\">}</span> <span class=\"token operator\">/</span><span class=\"token operator\">></span>\n      <span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">}</span>\n    <span class=\"token operator\">&lt;</span><span class=\"token operator\">/</span>ul<span class=\"token operator\">></span>\n  <span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>Ratkaisu on elegantti! </p>\n<blockquote>\n<h4>Mahdollinen vaihtoehtoinen ratkaisu</h4>\n<p>Eräs vaihtoehto olisi toteuttaa filtteröinti suoraan selektorifunktion sisällä, jolloin sekä muistiinpanot että filtteri luettaisiin yhdellä <i>useNoteStore</i>-kutsulla:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token keyword\">export</span> <span class=\"token keyword\">const</span> <span class=\"token function-variable function\">useNotes</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token function\">useNoteStore</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token parameter\"><span class=\"token punctuation\">{</span> notes<span class=\"token punctuation\">,</span> filter <span class=\"token punctuation\">}</span></span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>filter <span class=\"token operator\">===</span> <span class=\"token string\">'important'</span><span class=\"token punctuation\">)</span> <span class=\"token keyword\">return</span> notes<span class=\"token punctuation\">.</span><span class=\"token function\">filter</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">n</span> <span class=\"token operator\">=></span> n<span class=\"token punctuation\">.</span>important<span class=\"token punctuation\">)</span>\n <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>filter <span class=\"token operator\">===</span> <span class=\"token string\">'nonimportant'</span><span class=\"token punctuation\">)</span> <span class=\"token keyword\">return</span> notes<span class=\"token punctuation\">.</span><span class=\"token function\">filter</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">n</span> <span class=\"token operator\">=></span> <span class=\"token operator\">!</span>n<span class=\"token punctuation\">.</span>important<span class=\"token punctuation\">)</span>\n <span class=\"token keyword\">return</span> notes\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>Tämä tie kuitenkaan toimi, vaan johtaa loputtomaan uudelleenrenderöintisilmukkaan, kun filtteriä vaihdetaan. </p>\n<p>Syy on seuraava: Zustand vertaa selektorin paluuarvoa <i>===</i>-operaattorilla. Koska <i>notes.filter(...)</i> luo joka renderöinnillä uuden taulukon, React tulkitsee sen aina uudeksi tilaksi ja käynnistää uuden renderöinnin, joka taas luo uuden taulukon, ja niin edelleen.</p>\n<p>Korjaus on lisätä <a href=\"https://zustand.docs.pmnd.rs/reference/hooks/use-shallow\">useShallow</a>, joka korvaa <i>===</i>-vertailun \"matalalla\" vertailulla eli se ainoastaan vertaa taulukon alkioita yksitellen. Jos sisältö ei ole muuttunut, se palauttaa vanhan taulukon viitteen, jolloin React näkee tilan samana kuin aiemmin eikä renderöi komponenttia uudelleen.</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token keyword\">import</span> <span class=\"token punctuation\">{</span> useShallow <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">'zustand/react/shallow'</span>\n\n<span class=\"token comment\">//...</span>\n\n<span class=\"token keyword\">export</span> <span class=\"token keyword\">const</span> <span class=\"token function-variable function\">useNotes</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token function\">useNoteStore</span><span class=\"token punctuation\">(</span><span class=\"token function\">useShallow</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token parameter\"><span class=\"token punctuation\">{</span> notes<span class=\"token punctuation\">,</span> filter <span class=\"token punctuation\">}</span></span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>filter <span class=\"token operator\">===</span> <span class=\"token string\">'important'</span><span class=\"token punctuation\">)</span> <span class=\"token keyword\">return</span> notes<span class=\"token punctuation\">.</span><span class=\"token function\">filter</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">n</span> <span class=\"token operator\">=></span> n<span class=\"token punctuation\">.</span>important<span class=\"token punctuation\">)</span>\n <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>filter <span class=\"token operator\">===</span> <span class=\"token string\">'nonimportant'</span><span class=\"token punctuation\">)</span> <span class=\"token keyword\">return</span> notes<span class=\"token punctuation\">.</span><span class=\"token function\">filter</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">n</span> <span class=\"token operator\">=></span> <span class=\"token operator\">!</span>n<span class=\"token punctuation\">.</span>important<span class=\"token punctuation\">)</span>\n <span class=\"token keyword\">return</span> notes\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>Ratkaisu toimii, mutta se on hieman hankalampi ymmärtää. Käytämmekin materiaalissa aiemmin esitettyä kahden erillisen <i>useNoteStore</i>-kutsun versiota.</p>\n</blockquote>\n<p>Sovelluksen tämänhetkinen koodi on kokonaisuudessaan <a href=\"https://github.com/fullstack-hy2020/zustand-notes/tree/part6-3\">GitHubissa</a>, branchissa <i>part6-3</i>.</p>\n</div>\n<div class=\"tasks\">\n<h3>Tehtävä 6.6</h3>\n<p>Jatketaan anekdoottisovelluksen parissa.</p>\n<h4>6.6 anekdootit, step5</h4>\n<p>Toteuta sovellukseen näytettävien anekdoottien filtteröiminen:</p>\n<picture><img src=\"/static/1665ded20b15958ef98ad6e92a140fd9/5a190/u3.png\" alt=\"Yläosaan lisätään tekstikenttä, johon kirjoittamalla voidaan rajoittaa näytettävät anekdootit niihin joihin sisältyy &#x22;filtterikenttään&#x22; kirjoitettu merkkijono\" srcset=\"/static/1665ded20b15958ef98ad6e92a140fd9/772e8/u3.png 200w,\n/static/1665ded20b15958ef98ad6e92a140fd9/e17e5/u3.png 400w,\n/static/1665ded20b15958ef98ad6e92a140fd9/5a190/u3.png 800w,\n/static/1665ded20b15958ef98ad6e92a140fd9/c1b63/u3.png 1200w,\n/static/1665ded20b15958ef98ad6e92a140fd9/07d7d/u3.png 1478w\" sizes=\"(max-width: 800px) 100vw, 800px\"></picture>\n<p>Tee filtterin ruudulla näyttämistä varten komponentti <i>Filter</i>. Voit ottaa sen pohjaksi seuraavan koodin:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token keyword\">const</span> <span class=\"token function-variable function\">Filter</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">const</span> <span class=\"token function-variable function\">handleChange</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">event</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n    <span class=\"token comment\">// input-kentän arvo muuttujassa event.target.value</span>\n  <span class=\"token punctuation\">}</span>\n  <span class=\"token keyword\">const</span> style <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token literal-property property\">marginBottom</span><span class=\"token operator\">:</span> <span class=\"token number\">10</span>\n  <span class=\"token punctuation\">}</span>\n\n  <span class=\"token keyword\">return</span> <span class=\"token punctuation\">(</span>\n    <span class=\"token operator\">&lt;</span>div style<span class=\"token operator\">=</span><span class=\"token punctuation\">{</span>style<span class=\"token punctuation\">}</span><span class=\"token operator\">></span>\n      filter <span class=\"token operator\">&lt;</span>input onChange<span class=\"token operator\">=</span><span class=\"token punctuation\">{</span>handleChange<span class=\"token punctuation\">}</span> <span class=\"token operator\">/</span><span class=\"token operator\">></span>\n    <span class=\"token operator\">&lt;</span><span class=\"token operator\">/</span>div<span class=\"token operator\">></span>\n  <span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">}</span>\n\n<span class=\"token keyword\">export</span> <span class=\"token keyword\">default</span> Filter</code></pre></div>\n</div>\n<div class=\"content\">\n<h3>Data palvelimelle</h3>\n<p>Laajennetaan sovellusta siten, että muistiinpanot talletetaan backendiin. Käytetään osasta 2 tuttua <a href=\"/osa2/palvelimella_olevan_datan_hakeminen\">JSON Serveriä</a>.</p>\n<p>Tallennetaan projektin juureen tiedostoon <i>db.json</i> tietokannan alkutila:</p>\n<div class=\"gatsby-highlight\" data-language=\"json\"><pre class=\"language-json\"><code class=\"language-json\"><span class=\"token punctuation\">{</span>\n  <span class=\"token property\">\"notes\"</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span>\n    <span class=\"token punctuation\">{</span>\n      <span class=\"token property\">\"id\"</span><span class=\"token operator\">:</span> <span class=\"token number\">1</span><span class=\"token punctuation\">,</span>\n      <span class=\"token property\">\"content\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"Zustand is less complex than Redux\"</span><span class=\"token punctuation\">,</span>\n      <span class=\"token property\">\"important\"</span><span class=\"token operator\">:</span> <span class=\"token boolean\">true</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n    <span class=\"token punctuation\">{</span>\n      <span class=\"token property\">\"id\"</span><span class=\"token operator\">:</span> <span class=\"token number\">2</span><span class=\"token punctuation\">,</span>\n      <span class=\"token property\">\"content\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"React app benefits from custom hooks\"</span><span class=\"token punctuation\">,</span>\n      <span class=\"token property\">\"important\"</span><span class=\"token operator\">:</span> <span class=\"token boolean\">false</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n    <span class=\"token punctuation\">{</span>\n      <span class=\"token property\">\"id\"</span><span class=\"token operator\">:</span> <span class=\"token number\">3</span><span class=\"token punctuation\">,</span>\n      <span class=\"token property\">\"content\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"Remember to sleep well\"</span><span class=\"token punctuation\">,</span>\n      <span class=\"token property\">\"important\"</span><span class=\"token operator\">:</span> <span class=\"token boolean\">true</span>\n    <span class=\"token punctuation\">}</span>\n  <span class=\"token punctuation\">]</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>Asennetaan projektiin JSON Server</p>\n<div class=\"gatsby-highlight\" data-language=\"bash\"><pre class=\"language-bash\"><code class=\"language-bash\"><span class=\"token function\">npm</span> <span class=\"token function\">install</span> json-server --save-dev</code></pre></div>\n<p>ja lisätään tiedoston <i>package.json</i> osaan <i>scripts</i> rivi</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token string-property property\">\"scripts\"</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token string-property property\">\"server\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"json-server -p 3001 db.json\"</span><span class=\"token punctuation\">,</span>\n  <span class=\"token comment\">// ...</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>Käynnistetään JSON Server komennolla <em>npm run server</em>.</p>\n<h3>Fetch API</h3>\n<p>Ohjelmistokehityksessä joudutaan usein pohtimaan, kannattaako jokin toiminnallisuus toteuttaa käyttämällä ulkoista kirjastoa vai onko parempi hyödyntää ympäristön tarjoamia natiiveja ratkaisuja. Molemmilla lähestymistavoilla on omat etunsa ja haasteensa. </p>\n<p>Olemme käyttäneet HTTP-pyyntöjen tekemiseen kurssin aiemmissa osissa <a href=\"https://axios-http.com/docs/intro\">Axios</a>-kirjastoa. Tutustutaan nyt vaihtoehtoiseen tapaan tehdä HTTP-pyyntöjä natiivia <a href=\"https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API\">Fetch APIa</a> hyödyntäen.</p>\n<p>On tyypillistä, että ulkoinen kirjasto kuten <i>Axios</i> on toteutettu hyödyntäen muita ulkoisia kirjastoja. Esimerkiksi jos Axioksen asentaa projektiin komennolla <i>npm install axios</i>, konsoliin tulostuu: </p>\n<div class=\"gatsby-highlight\" data-language=\"bash\"><pre class=\"language-bash\"><code class=\"language-bash\">$ <span class=\"token function\">npm</span> <span class=\"token function\">install</span> axios\n\nadded <span class=\"token number\">23</span> packages, and audited <span class=\"token number\">302</span> packages <span class=\"token keyword\">in</span> 1s\n\n<span class=\"token number\">71</span> packages are looking <span class=\"token keyword\">for</span> funding\n  run <span class=\"token variable\"><span class=\"token variable\">`</span><span class=\"token function\">npm</span> fund<span class=\"token variable\">`</span></span> <span class=\"token keyword\">for</span> details\n\nfound <span class=\"token number\">0</span> vulnerabilities</code></pre></div>\n<p>Komento asentaisi projektiin siis Axios-kirjaston lisäksi yli 20 muuta npm-pakettia, jotka Axios tarvitsisi toimiakseen. </p>\n<p><i>Fetch API</i> tarjoaa samankaltaisen tavan tehdä HTTP-pyyntöjä kuin Axios, mutta Fetch APIn käyttäminen ei vaadi ulkoisten kirjastojen asentamista. Sovelluksen ylläpito helpottuu, kun päivitettäviä kirjastoja on vähemmän, ja myös tietoturva paranee, koska sovelluksen mahdollinen hyökkäyspinta-ala pienenee. Sovellusten tietoturvaa ja ylläpitoa sivutaan kurssin <a href=\"https://fullstackopen.com/osa7/luokkakomponentit_sekalaista#react-node-sovellusten-tietoturva\">osassa 7</a>.</p>\n<p>Pyyntöjen tekeminen tapahtuu käytännössä käyttämällä <i>fetch()</i>-funktiota. Käytettävässä syntaksissa on jonkin verran eroja verrattuna Axiokseen. Huomaamme myös pian, että Axios on huolehtinut joistakin asioista puolestamme ja helpottanut elämäämme. Käytämme nyt kuitenkin Fetch APIa, koska se on laajasti käytetty natiiviratkaisu, joka jokaisen Full Stack -kehittäjän on syytä tuntea.</p>\n<h3>Datan hakeminen palvelimelta</h3>\n<p>Tehdään backendistä dataa hakeva funktio tiedostoon <i>src/services/notes.js</i>:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token keyword\">const</span> baseUrl <span class=\"token operator\">=</span> <span class=\"token string\">'http://localhost:3001/notes'</span>\n\n<span class=\"token keyword\">const</span> <span class=\"token function-variable function\">getAll</span> <span class=\"token operator\">=</span> <span class=\"token keyword\">async</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">const</span> response <span class=\"token operator\">=</span> <span class=\"token keyword\">await</span> <span class=\"token function\">fetch</span><span class=\"token punctuation\">(</span>baseUrl<span class=\"token punctuation\">)</span>\n\n  <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token operator\">!</span>response<span class=\"token punctuation\">.</span>ok<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">throw</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Error</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Failed to fetch notes'</span><span class=\"token punctuation\">)</span>\n  <span class=\"token punctuation\">}</span>\n\n  <span class=\"token keyword\">const</span> data <span class=\"token operator\">=</span> <span class=\"token keyword\">await</span> response<span class=\"token punctuation\">.</span><span class=\"token function\">json</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n  <span class=\"token keyword\">return</span> data\n<span class=\"token punctuation\">}</span>\n\n<span class=\"token keyword\">export</span> <span class=\"token keyword\">default</span> <span class=\"token punctuation\">{</span> getAll <span class=\"token punctuation\">}</span></code></pre></div>\n<p>Tutkitaan <i>getAll</i>-funktion toteutusta tarkemmin. Muistiinpanot haetaan backendistä nyt kutsumalla <i>fetch()</i>-funktiota, jolle on annettu argumentiksi backendin URL-osoite. Pyynnön tyyppiä ei ole erikseen määritelty, joten <i>fetch</i> toteuttaa oletusarvoisen toiminnon eli GET-pyynnön.</p>\n<p>Kun vastaus on saapunut, tarkistetaan pyynnön onnistuminen vastauksen kentästä <i>response.ok</i> ja heitetään tarvittaessa virhe:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token operator\">!</span>response<span class=\"token punctuation\">.</span>ok<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">throw</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Error</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Failed to fetch notes'</span><span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>Attribuutti <i>response.ok</i> saa arvon <i>true</i>, jos pyyntö on onnistunut eli jos vastauksen statuskoodi on välillä 200-299. Kaikilla muilla statuskoodeilla, esimerkiksi 404 tai 500, se saa arvon <i>false</i>. </p>\n<p>Huomaa, että <i>fetch</i> ei automaattisesti heitä virhettä, vaikka vastauksen statuskoodi olisi esimerkiksi 404. Virheenkäsittely tulee toteuttaa manuaalisesti, kuten olemme nyt tehneet.</p>\n<p>Jos pyyntö on onnistunut, vastauksen sisältämä data muunnetaan JSON-muotoon:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token keyword\">const</span> data <span class=\"token operator\">=</span> <span class=\"token keyword\">await</span> response<span class=\"token punctuation\">.</span><span class=\"token function\">json</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p><i>fetch</i> ei siis automaattisesti muunna vastauksen mukana mahdollisesti olevaa dataa JSON-muotoon, vaan muunnos tulee tehdä manuaalisesti. On myös hyvä huomata, että <i>response.json()</i> on asynkroninen funktio, eli sen kanssa tulee käyttää <i>await</i>-avainsanaa.</p>\n<p>Suoraviivaistetaan koodia vielä hieman palauttamalla suoraan funktion <i>response.json()</i> palauttama data:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token keyword\">const</span> <span class=\"token function-variable function\">getAll</span> <span class=\"token operator\">=</span> <span class=\"token keyword\">async</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">const</span> response <span class=\"token operator\">=</span> <span class=\"token keyword\">await</span> <span class=\"token function\">fetch</span><span class=\"token punctuation\">(</span>baseUrl<span class=\"token punctuation\">)</span>\n\n  <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token operator\">!</span>response<span class=\"token punctuation\">.</span>ok<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">throw</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Error</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Failed to fetch notes'</span><span class=\"token punctuation\">)</span>\n  <span class=\"token punctuation\">}</span>\n\n<span class=\"gatsby-highlight-code-line\">  <span class=\"token keyword\">return</span> <span class=\"token keyword\">await</span> response<span class=\"token punctuation\">.</span><span class=\"token function\">json</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></span><span class=\"token punctuation\">}</span></code></pre></div>\n<p>Lisätään storeen funktio, jonka avulla tila voidaan alustaa palvelimelta haettavilla muistiinpanoilla:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token keyword\">const</span> useNoteStore <span class=\"token operator\">=</span> <span class=\"token function\">create</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token parameter\"><span class=\"token keyword\">set</span></span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span>\n<span class=\"gatsby-highlight-code-line\">  <span class=\"token literal-property property\">notes</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span></span>  <span class=\"token literal-property property\">filter</span><span class=\"token operator\">:</span> <span class=\"token string\">''</span><span class=\"token punctuation\">,</span>\n  <span class=\"token literal-property property\">actions</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token comment\">// ...</span>\n    <span class=\"token function-variable function\">setFilter</span><span class=\"token operator\">:</span> <span class=\"token parameter\">value</span> <span class=\"token operator\">=></span> <span class=\"token function\">set</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">filter</span><span class=\"token operator\">:</span> value <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n<span class=\"gatsby-highlight-code-line\">    <span class=\"token function-variable function\">initialize</span><span class=\"token operator\">:</span> <span class=\"token parameter\">notes</span> <span class=\"token operator\">=></span> <span class=\"token function\">set</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span> notes <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span></span>  <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>Toteutetaan muistiinpanojen alustus <i>App</i>-komponentiin, eli kuten yleensä dataa palvelimelta haettaessa, käytetään <i>useEffect</i>-hookia:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token keyword\">const</span> <span class=\"token function-variable function\">App</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">const</span> <span class=\"token punctuation\">{</span> initialize <span class=\"token punctuation\">}</span> <span class=\"token operator\">=</span> <span class=\"token function\">useNoteActions</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n\n<span class=\"gatsby-highlight-code-line\">  <span class=\"token function\">useEffect</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span></span><span class=\"gatsby-highlight-code-line\">    noteService<span class=\"token punctuation\">.</span><span class=\"token function\">getAll</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">then</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">notes</span> <span class=\"token operator\">=></span> <span class=\"token function\">initialize</span><span class=\"token punctuation\">(</span>notes<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span></span><span class=\"gatsby-highlight-code-line\">  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">[</span>initialize<span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span></span>\n  <span class=\"token keyword\">return</span> <span class=\"token punctuation\">(</span>\n    <span class=\"token operator\">&lt;</span>div<span class=\"token operator\">></span>\n      <span class=\"token operator\">&lt;</span>NoteForm <span class=\"token operator\">/</span><span class=\"token operator\">></span>\n      <span class=\"token operator\">&lt;</span>VisibilityFilter <span class=\"token operator\">/</span><span class=\"token operator\">></span>\n      <span class=\"token operator\">&lt;</span>NoteList <span class=\"token operator\">/</span><span class=\"token operator\">></span>\n    <span class=\"token operator\">&lt;</span><span class=\"token operator\">/</span>div<span class=\"token operator\">></span>\n  <span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>Muistiinpanot haetaan palvelimelta siis käyttäen määrittelemäämme <i>getAll()</i>-function ja tallennetaan sitten storen funktiolla <i>initialize</i> . Toiminnot tehdään <i>useEffect</i>-hookissa eli ne suoritetaan App-komponentin ensimmäisen renderöinnin yhteydessä.</p>\n<p>Tutkitaan vielä tarkemmin erästä pientä yksityiskohtaa. Olemme lisänneet <i>initialize</i>-funktion <i>useEffect</i>-hookin riippuvuustaulukkoon. Jos yritämme käyttää tyhjää riippuvuustaulukkoa, ESLint antaa seuraavan varoituksen: <i>React Hook useEffect has a missing dependency: 'initialize'</i>. Mistä on kyse?</p>\n<p>Koodi toimisi loogisesti täysin samoin, vaikka käyttäisimme tyhjää riippuvuustaulukkoa, koska <i>initialize</i> viittaa samaan funktioon koko ohjelman suorituksen ajan. On kuitenkin hyvän ohjelmointikäytännön mukaista lisätä <i>useEffect</i>-hookin riippuvuuksiksi kaikki sen käyttämät muuttujat ja funktiot, jotka on määritelty kyseisen komponentin sisällä. Näin voidaan välttää yllättäviä bugeja.</p>\n<h3>Datan lähettäminen palvelimelle</h3>\n<p>Toteutetaan seuraavaksi toiminnallisuus uuden muistiinpanon lähettämiseksi palvelimelle. Pääsemme samalla harjoittelemaan, miten POST-pyyntö tehdään <i>fetch()</i>-funktiota käyttäen.</p>\n<p>Laajennetaan tiedostossa <i>src/services/notes.js</i> olevaa palvelimen kanssa kommunikoivaa koodia seuraavasti:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token keyword\">const</span> baseUrl <span class=\"token operator\">=</span> <span class=\"token string\">'http://localhost:3001/notes'</span>\n\n<span class=\"token keyword\">const</span> <span class=\"token function-variable function\">getAll</span> <span class=\"token operator\">=</span> <span class=\"token keyword\">async</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">const</span> response <span class=\"token operator\">=</span> <span class=\"token keyword\">await</span> <span class=\"token function\">fetch</span><span class=\"token punctuation\">(</span>baseUrl<span class=\"token punctuation\">)</span>\n\n  <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token operator\">!</span>response<span class=\"token punctuation\">.</span>ok<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">throw</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Error</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Failed to fetch notes'</span><span class=\"token punctuation\">)</span>\n  <span class=\"token punctuation\">}</span>\n\n  <span class=\"token keyword\">return</span> <span class=\"token keyword\">await</span> response<span class=\"token punctuation\">.</span><span class=\"token function\">json</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">}</span>\n\n<span class=\"gatsby-highlight-code-line\"><span class=\"token keyword\">const</span> <span class=\"token function-variable function\">createNew</span> <span class=\"token operator\">=</span> <span class=\"token keyword\">async</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">content</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span></span><span class=\"gatsby-highlight-code-line\">  <span class=\"token keyword\">const</span> response <span class=\"token operator\">=</span> <span class=\"token keyword\">await</span> <span class=\"token function\">fetch</span><span class=\"token punctuation\">(</span>baseUrl<span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span></span><span class=\"gatsby-highlight-code-line\">    <span class=\"token literal-property property\">method</span><span class=\"token operator\">:</span> <span class=\"token string\">'POST'</span><span class=\"token punctuation\">,</span></span><span class=\"gatsby-highlight-code-line\">    <span class=\"token literal-property property\">headers</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span> <span class=\"token string-property property\">'Content-Type'</span><span class=\"token operator\">:</span> <span class=\"token string\">'application/json'</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span></span><span class=\"gatsby-highlight-code-line\">    <span class=\"token literal-property property\">body</span><span class=\"token operator\">:</span> <span class=\"token constant\">JSON</span><span class=\"token punctuation\">.</span><span class=\"token function\">stringify</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span> content<span class=\"token punctuation\">,</span> <span class=\"token literal-property property\">important</span><span class=\"token operator\">:</span> <span class=\"token boolean\">false</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span></span><span class=\"gatsby-highlight-code-line\">  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span></span><span class=\"gatsby-highlight-code-line\">  </span><span class=\"gatsby-highlight-code-line\">  <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token operator\">!</span>response<span class=\"token punctuation\">.</span>ok<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span></span><span class=\"gatsby-highlight-code-line\">    <span class=\"token keyword\">throw</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Error</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Failed to create note'</span><span class=\"token punctuation\">)</span></span><span class=\"gatsby-highlight-code-line\">  <span class=\"token punctuation\">}</span></span><span class=\"gatsby-highlight-code-line\">  </span><span class=\"gatsby-highlight-code-line\">  <span class=\"token keyword\">return</span> <span class=\"token keyword\">await</span> response<span class=\"token punctuation\">.</span><span class=\"token function\">json</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></span><span class=\"gatsby-highlight-code-line\"><span class=\"token punctuation\">}</span></span>\n<span class=\"gatsby-highlight-code-line\"><span class=\"token keyword\">export</span> <span class=\"token keyword\">default</span> <span class=\"token punctuation\">{</span> getAll<span class=\"token punctuation\">,</span> createNew <span class=\"token punctuation\">}</span></span></code></pre></div>\n<p>Tutkitaan <i>createNew</i>-funktion toteutusta tarkemmin. <i>fetch()</i>-funktion ensimmäinen parametri määrittelee URL-osoitteen, johon pyyntö tehdään. Toinen parametri on olio, joka määrittelee muut pyynnön yksityiskohdat, kuten pyynnön tyypin, otsikot ja pyynnön mukana lähetettävän datan. Voimme selkeyttää koodia vielä hieman tallentamalla pyynnön yksityiskohdat määrittelevän olion erilliseen <i>options</i>-apumuuttujaan:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token keyword\">const</span> <span class=\"token function-variable function\">createNew</span> <span class=\"token operator\">=</span> <span class=\"token keyword\">async</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">content</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n<span class=\"gatsby-highlight-code-line\">  <span class=\"token keyword\">const</span> options <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span></span><span class=\"gatsby-highlight-code-line\">    <span class=\"token literal-property property\">method</span><span class=\"token operator\">:</span> <span class=\"token string\">'POST'</span><span class=\"token punctuation\">,</span></span><span class=\"gatsby-highlight-code-line\">    <span class=\"token literal-property property\">headers</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span> <span class=\"token string-property property\">'Content-Type'</span><span class=\"token operator\">:</span> <span class=\"token string\">'application/json'</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span></span><span class=\"gatsby-highlight-code-line\">    <span class=\"token literal-property property\">body</span><span class=\"token operator\">:</span> <span class=\"token constant\">JSON</span><span class=\"token punctuation\">.</span><span class=\"token function\">stringify</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span> content<span class=\"token punctuation\">,</span> <span class=\"token literal-property property\">important</span><span class=\"token operator\">:</span> <span class=\"token boolean\">false</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span></span><span class=\"gatsby-highlight-code-line\">  <span class=\"token punctuation\">}</span></span><span class=\"gatsby-highlight-code-line\">  </span><span class=\"gatsby-highlight-code-line\">  <span class=\"token keyword\">const</span> response <span class=\"token operator\">=</span> <span class=\"token keyword\">await</span> <span class=\"token function\">fetch</span><span class=\"token punctuation\">(</span>baseUrl<span class=\"token punctuation\">,</span> options<span class=\"token punctuation\">)</span></span>\n  <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token operator\">!</span>response<span class=\"token punctuation\">.</span>ok<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">throw</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Error</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Failed to create note'</span><span class=\"token punctuation\">)</span>\n  <span class=\"token punctuation\">}</span>\n  \n  <span class=\"token keyword\">return</span> <span class=\"token keyword\">await</span> response<span class=\"token punctuation\">.</span><span class=\"token function\">json</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>Tutkitaan <i>options</i>-oliota tarkemmin:</p>\n<ul>\n<li><i>method</i> määrittelee pyynnön tyypin, joka tässä tapauksessa on <i>POST</i></li>\n<li><i>headers</i> määrittelee pyynnön otsikot. Liitämme pyyntöön otsikon <i>'Content-Type': 'application/json'</i>, jotta palvelin tietää, että pyynnön mukana oleva data on JSON-muotoista, ja osaa käsitellä pyynnön oikein</li>\n<li><i>body</i> sisältää pyynnön mukana lähetettävän datan. Kenttään ei voi suoraan sijoittaa JavaScript-oliota, vaan se tulee ensin muuntaa JSON-merkkijonoksi kutsumalla funktiota <i>JSON.stringify()</i></li>\n</ul>\n<p>Kuten GET-pyynnön kanssa, myös nyt vastauksen statuskoodi tutkitaan virheiden varalta:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token operator\">!</span>response<span class=\"token punctuation\">.</span>ok<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">throw</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Error</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Failed to create note'</span><span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>Jos pyyntö onnistuu, <i>JSON Server</i> palauttaa juuri luodun muistiinpanon, jolle se on generoinut myös yksilöllisen <i>id</i>:n. Vastauksen sisältämä data tulee kuitenkin vielä muuntaa JSON-muotoon funktiolla <i>response.json()</i>: </p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token keyword\">return</span> <span class=\"token keyword\">await</span> response<span class=\"token punctuation\">.</span><span class=\"token function\">json</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>Muutetaan sitten sovelluksemme <i>NoteForm</i>-komponenttia siten, että uusi muistiinpano lähetetään backendiin. Komponentin funktio <i>addNote</i> muuttuu hiukan:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token keyword\">import</span> <span class=\"token punctuation\">{</span> useNoteActions <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">'./store'</span>\n<span class=\"token keyword\">import</span> noteService <span class=\"token keyword\">from</span> <span class=\"token string\">'./services/notes'</span>\n\n<span class=\"token keyword\">const</span> <span class=\"token function-variable function\">NoteForm</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">const</span> <span class=\"token punctuation\">{</span> add <span class=\"token punctuation\">}</span> <span class=\"token operator\">=</span> <span class=\"token function\">useNoteActions</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n\n  <span class=\"token keyword\">const</span> <span class=\"token function-variable function\">addNote</span> <span class=\"token operator\">=</span> <span class=\"token keyword\">async</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">e</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n    e<span class=\"token punctuation\">.</span><span class=\"token function\">preventDefault</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n    <span class=\"token keyword\">const</span> content <span class=\"token operator\">=</span> e<span class=\"token punctuation\">.</span>target<span class=\"token punctuation\">.</span>note<span class=\"token punctuation\">.</span>value\n<span class=\"gatsby-highlight-code-line\">    <span class=\"token keyword\">const</span> newNote <span class=\"token operator\">=</span> <span class=\"token keyword\">await</span> noteService<span class=\"token punctuation\">.</span><span class=\"token function\">createNew</span><span class=\"token punctuation\">(</span>content<span class=\"token punctuation\">)</span></span>    <span class=\"token function\">add</span><span class=\"token punctuation\">(</span>newNote<span class=\"token punctuation\">)</span>\n    e<span class=\"token punctuation\">.</span>target<span class=\"token punctuation\">.</span><span class=\"token function\">reset</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n  <span class=\"token punctuation\">}</span>\n\n  <span class=\"token keyword\">return</span> <span class=\"token punctuation\">(</span>\n    <span class=\"token operator\">&lt;</span>form onSubmit<span class=\"token operator\">=</span><span class=\"token punctuation\">{</span>addNote<span class=\"token punctuation\">}</span><span class=\"token operator\">></span>\n      <span class=\"token operator\">&lt;</span>input name<span class=\"token operator\">=</span><span class=\"token string\">\"note\"</span> <span class=\"token operator\">/</span><span class=\"token operator\">></span>\n      <span class=\"token operator\">&lt;</span>button type<span class=\"token operator\">=</span><span class=\"token string\">\"submit\"</span><span class=\"token operator\">></span>add<span class=\"token operator\">&lt;</span><span class=\"token operator\">/</span>button<span class=\"token operator\">></span>\n    <span class=\"token operator\">&lt;</span><span class=\"token operator\">/</span>form<span class=\"token operator\">></span>\n  <span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">}</span>\n\n<span class=\"token keyword\">export</span> <span class=\"token keyword\">default</span> NoteForm</code></pre></div>\n<p>Kun uusi muistiinpano luodaan backendiin kutsumalla funktiota <i>createNew()</i>, saadaan paluuarvona muistiinpanoa kuvaava olio, jolle backend on generoinut <i>id</i>:n.</p>\n<p>Sovelluksen tämänhetkinen koodi on kokonaisuudessaan <a href=\"https://github.com/fullstack-hy2020/zustand-notes/tree/part6-4\">GitHubissa</a>, branchissa <i>part6-4</i>.</p>\n<h3>Asynkroniset actionit</h3>\n<p>Lähestymistapamme on melko hyvä, mutta siinä mielessä ikävä, että palvelimen kanssa kommunikointi tapahtuu komponentit määrittelevien funktioiden koodissa. Olisi parempi, jos kommunikointi voitaisiin abstrahoida komponenteilta siten, että niiden ei tarvitsisi kuin kutsua sopivaa storen tarjoamaa funktiota. </p>\n<p>Haluammekin, että <i>App</i> alustaa sovelluksen tilan seuraavasti:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token keyword\">const</span> <span class=\"token function-variable function\">App</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n<span class=\"gatsby-highlight-code-line\">  <span class=\"token keyword\">const</span> <span class=\"token punctuation\">{</span> initialize <span class=\"token punctuation\">}</span> <span class=\"token operator\">=</span> <span class=\"token function\">useNoteActions</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></span>\n  <span class=\"token function\">useEffect</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n<span class=\"gatsby-highlight-code-line\">    <span class=\"token function\">initialize</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></span>  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">[</span>initialize<span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span>\n\n  <span class=\"token keyword\">return</span> <span class=\"token punctuation\">(</span>\n    <span class=\"token operator\">&lt;</span>div<span class=\"token operator\">></span>\n      <span class=\"token operator\">&lt;</span>NoteForm <span class=\"token operator\">/</span><span class=\"token operator\">></span>\n      <span class=\"token operator\">&lt;</span>VisibilityFilter <span class=\"token operator\">/</span><span class=\"token operator\">></span>\n      <span class=\"token operator\">&lt;</span>NoteList <span class=\"token operator\">/</span><span class=\"token operator\">></span>\n    <span class=\"token operator\">&lt;</span><span class=\"token operator\">/</span>div<span class=\"token operator\">></span>\n  <span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p><i>NoteForm</i> puolestaan luo uuden muistiinpanon näin:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token keyword\">const</span> <span class=\"token function-variable function\">NoteForm</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n<span class=\"gatsby-highlight-code-line\">  <span class=\"token keyword\">const</span> <span class=\"token punctuation\">{</span> add <span class=\"token punctuation\">}</span> <span class=\"token operator\">=</span> <span class=\"token function\">useNoteActions</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></span>\n  <span class=\"token keyword\">const</span> <span class=\"token function-variable function\">addNote</span> <span class=\"token operator\">=</span> <span class=\"token keyword\">async</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">e</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n    e<span class=\"token punctuation\">.</span><span class=\"token function\">preventDefault</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n    <span class=\"token keyword\">const</span> content <span class=\"token operator\">=</span> e<span class=\"token punctuation\">.</span>target<span class=\"token punctuation\">.</span>note<span class=\"token punctuation\">.</span>value\n<span class=\"gatsby-highlight-code-line\">    <span class=\"token keyword\">await</span> <span class=\"token function\">add</span><span class=\"token punctuation\">(</span>content<span class=\"token punctuation\">)</span></span>    e<span class=\"token punctuation\">.</span>target<span class=\"token punctuation\">.</span><span class=\"token function\">reset</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n  <span class=\"token punctuation\">}</span>\n\n  <span class=\"token keyword\">return</span> <span class=\"token punctuation\">(</span>\n    <span class=\"token operator\">&lt;</span>form onSubmit<span class=\"token operator\">=</span><span class=\"token punctuation\">{</span>addNote<span class=\"token punctuation\">}</span><span class=\"token operator\">></span>\n      <span class=\"token operator\">&lt;</span>input name<span class=\"token operator\">=</span><span class=\"token string\">\"note\"</span> <span class=\"token operator\">/</span><span class=\"token operator\">></span>\n      <span class=\"token operator\">&lt;</span>button type<span class=\"token operator\">=</span><span class=\"token string\">\"submit\"</span><span class=\"token operator\">></span>add<span class=\"token operator\">&lt;</span><span class=\"token operator\">/</span>button<span class=\"token operator\">></span>\n    <span class=\"token operator\">&lt;</span><span class=\"token operator\">/</span>form<span class=\"token operator\">></span>\n  <span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>Tiedostoon <i>store.js</i> tehtävä muutos on seuraava:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token keyword\">import</span> <span class=\"token punctuation\">{</span> create <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">'zustand'</span>\n<span class=\"gatsby-highlight-code-line\"><span class=\"token keyword\">import</span> noteService <span class=\"token keyword\">from</span> <span class=\"token string\">'./services/notes'</span></span>\n<span class=\"token keyword\">const</span> useNoteStore <span class=\"token operator\">=</span> <span class=\"token function\">create</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token parameter\"><span class=\"token keyword\">set</span></span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span>\n  <span class=\"token literal-property property\">notes</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n  <span class=\"token literal-property property\">filter</span><span class=\"token operator\">:</span> <span class=\"token string\">''</span><span class=\"token punctuation\">,</span>\n  <span class=\"token literal-property property\">actions</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span>\n<span class=\"gatsby-highlight-code-line\">    <span class=\"token function-variable function\">add</span><span class=\"token operator\">:</span> <span class=\"token keyword\">async</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">content</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span></span><span class=\"gatsby-highlight-code-line\">      <span class=\"token keyword\">const</span> newNote <span class=\"token operator\">=</span> <span class=\"token keyword\">await</span> noteService<span class=\"token punctuation\">.</span><span class=\"token function\">createNew</span><span class=\"token punctuation\">(</span>content<span class=\"token punctuation\">)</span></span>      <span class=\"token function\">set</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">state</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">notes</span><span class=\"token operator\">:</span> state<span class=\"token punctuation\">.</span>notes<span class=\"token punctuation\">.</span><span class=\"token function\">concat</span><span class=\"token punctuation\">(</span>newNote<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n<span class=\"gatsby-highlight-code-line\">    <span class=\"token function-variable function\">initialize</span><span class=\"token operator\">:</span> <span class=\"token keyword\">async</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span></span><span class=\"gatsby-highlight-code-line\">      <span class=\"token keyword\">const</span> notes <span class=\"token operator\">=</span> <span class=\"token keyword\">await</span> noteService<span class=\"token punctuation\">.</span><span class=\"token function\">getAll</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></span>      <span class=\"token function\">set</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span> notes <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n    <span class=\"token comment\">// ...</span>\n  <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>Funktiot <i>add</i> ja <i>initialize</i> on siis muutettu asynkronisiksi funktioiksi, jotka kutsuvat ensin sopivaa noteServicen funktiota, ja päivittävät tilan tämän jälkeen.</p>\n<p>Ratkaisu on tyylikäs, tilan käsittely ja palvelimen kanssa kommunikointi on kokonaisuudessaan eriytetty React-komponenttien ulkopuolelle.</p>\n<p>Viimeistellään vielä sovellus siten, että muistiinpanojen tärkeyden muutos synkronoidaan palvelimelle.</p>\n<p><i>noteService.js</i> laajenee seuraavasti:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token keyword\">const</span> <span class=\"token function-variable function\">update</span> <span class=\"token operator\">=</span> <span class=\"token keyword\">async</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">id<span class=\"token punctuation\">,</span> note</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">const</span> response <span class=\"token operator\">=</span> <span class=\"token keyword\">await</span> <span class=\"token function\">fetch</span><span class=\"token punctuation\">(</span><span class=\"token template-string\"><span class=\"token template-punctuation string\">`</span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">${</span>baseUrl<span class=\"token interpolation-punctuation punctuation\">}</span></span><span class=\"token string\">/</span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">${</span>id<span class=\"token interpolation-punctuation punctuation\">}</span></span><span class=\"token template-punctuation string\">`</span></span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token literal-property property\">method</span><span class=\"token operator\">:</span> <span class=\"token string\">'PUT'</span><span class=\"token punctuation\">,</span>\n    <span class=\"token literal-property property\">headers</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span> <span class=\"token string-property property\">'Content-Type'</span><span class=\"token operator\">:</span> <span class=\"token string\">'application/json'</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n    <span class=\"token literal-property property\">body</span><span class=\"token operator\">:</span> <span class=\"token constant\">JSON</span><span class=\"token punctuation\">.</span><span class=\"token function\">stringify</span><span class=\"token punctuation\">(</span>note<span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n\n  <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token operator\">!</span>response<span class=\"token punctuation\">.</span>ok<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">throw</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Error</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Failed to update note'</span><span class=\"token punctuation\">)</span>\n  <span class=\"token punctuation\">}</span>\n\n  <span class=\"token keyword\">return</span> <span class=\"token keyword\">await</span> response<span class=\"token punctuation\">.</span><span class=\"token function\">json</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">}</span>\n\n<span class=\"token keyword\">export</span> <span class=\"token keyword\">default</span> <span class=\"token punctuation\">{</span> getAll<span class=\"token punctuation\">,</span> createNew<span class=\"token punctuation\">,</span> update <span class=\"token punctuation\">}</span> </code></pre></div>\n<p>Storen funktion <i>toggleImportance</i> muutos on seuraava</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token keyword\">const</span> useNoteStore <span class=\"token operator\">=</span> <span class=\"token function\">create</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token parameter\"><span class=\"token keyword\">set</span></span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span>\n  <span class=\"token literal-property property\">notes</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n  <span class=\"token literal-property property\">filter</span><span class=\"token operator\">:</span> <span class=\"token string\">''</span><span class=\"token punctuation\">,</span>\n  <span class=\"token literal-property property\">actions</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token function-variable function\">add</span><span class=\"token operator\">:</span> <span class=\"token keyword\">async</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">content</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n      <span class=\"token keyword\">const</span> newNote <span class=\"token operator\">=</span> <span class=\"token keyword\">await</span> noteService<span class=\"token punctuation\">.</span><span class=\"token function\">createNew</span><span class=\"token punctuation\">(</span>content<span class=\"token punctuation\">)</span>\n      <span class=\"token function\">set</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">state</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">notes</span><span class=\"token operator\">:</span> state<span class=\"token punctuation\">.</span>notes<span class=\"token punctuation\">.</span><span class=\"token function\">concat</span><span class=\"token punctuation\">(</span>newNote<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n<span class=\"gatsby-highlight-code-line\">    <span class=\"token function-variable function\">toggleImportance</span><span class=\"token operator\">:</span> <span class=\"token keyword\">async</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">id</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span></span><span class=\"gatsby-highlight-code-line\">      <span class=\"token keyword\">const</span> note <span class=\"token operator\">=</span> useNoteStore<span class=\"token punctuation\">.</span><span class=\"token function\">getState</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span>notes<span class=\"token punctuation\">.</span><span class=\"token function\">find</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">n</span> <span class=\"token operator\">=></span> n<span class=\"token punctuation\">.</span>id <span class=\"token operator\">===</span> id<span class=\"token punctuation\">)</span></span><span class=\"gatsby-highlight-code-line\">      <span class=\"token keyword\">const</span> updated <span class=\"token operator\">=</span> <span class=\"token keyword\">await</span> noteService<span class=\"token punctuation\">.</span><span class=\"token function\">update</span><span class=\"token punctuation\">(</span></span><span class=\"gatsby-highlight-code-line\">        id<span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span> <span class=\"token operator\">...</span>note<span class=\"token punctuation\">,</span> <span class=\"token literal-property property\">important</span><span class=\"token operator\">:</span> <span class=\"token operator\">!</span>note<span class=\"token punctuation\">.</span>important <span class=\"token punctuation\">}</span></span><span class=\"gatsby-highlight-code-line\">      <span class=\"token punctuation\">)</span></span><span class=\"gatsby-highlight-code-line\">      <span class=\"token function\">set</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">state</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span></span><span class=\"gatsby-highlight-code-line\">        <span class=\"token literal-property property\">notes</span><span class=\"token operator\">:</span> state<span class=\"token punctuation\">.</span>notes<span class=\"token punctuation\">.</span><span class=\"token function\">map</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">n</span> <span class=\"token operator\">=></span> n<span class=\"token punctuation\">.</span>id <span class=\"token operator\">===</span> id <span class=\"token operator\">?</span> updated <span class=\"token operator\">:</span> n<span class=\"token punctuation\">)</span></span><span class=\"gatsby-highlight-code-line\">      <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span></span><span class=\"gatsby-highlight-code-line\">    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span></span>    <span class=\"token function-variable function\">setFilter</span><span class=\"token operator\">:</span> <span class=\"token parameter\">value</span> <span class=\"token operator\">=></span> <span class=\"token function\">set</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">filter</span><span class=\"token operator\">:</span> value <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n    <span class=\"token function-variable function\">initialize</span><span class=\"token operator\">:</span> <span class=\"token keyword\">async</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n      <span class=\"token keyword\">const</span> notes <span class=\"token operator\">=</span> <span class=\"token keyword\">await</span> noteService<span class=\"token punctuation\">.</span><span class=\"token function\">getAll</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n      <span class=\"token function\">set</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span> notes <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">}</span>\n  <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>Uudessa funktiossa on eräs huomionarvoinen seikka. Funktio saa parametrina muistiinpanon id:n. Backendiin on kuitenkin lähetettävä muutettu muistiinpano. Se saadaan selville kutsumalla storen funktiota <i>getState</i>:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token keyword\">const</span> note <span class=\"token operator\">=</span> useNoteStore<span class=\"token punctuation\">.</span><span class=\"token function\">getState</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span>notes<span class=\"token punctuation\">.</span><span class=\"token function\">find</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">n</span> <span class=\"token operator\">=></span> n<span class=\"token punctuation\">.</span>id <span class=\"token operator\">===</span> id<span class=\"token punctuation\">)</span></code></pre></div>\n<p>Zustand-storeilla on myös joukko muita <a href=\"https://zustand.docs.pmnd.rs/reference/apis/create#returns\">apufunktioita</a>, mille saattaa olla joissain tilanteissa käyttöä. </p>\n<p>Muutetaan kuitenkin vielä storen määrittelyä siten, että välitetään <i>createlle</i> annettavalle funktiolle myös parametri <i>get</i>, jonka kautta pääsemme tarpeen tullen käsiksi tilan arvoihin:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"gatsby-highlight-code-line\"><span class=\"token keyword\">const</span> useNoteStore <span class=\"token operator\">=</span> <span class=\"token function\">create</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">set<span class=\"token punctuation\">,</span> <span class=\"token keyword\">get</span></span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span></span>  <span class=\"token literal-property property\">notes</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n  <span class=\"token literal-property property\">filter</span><span class=\"token operator\">:</span> <span class=\"token string\">''</span><span class=\"token punctuation\">,</span>\n  <span class=\"token literal-property property\">actions</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token function-variable function\">toggleImportance</span><span class=\"token operator\">:</span> <span class=\"token keyword\">async</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">id</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n<span class=\"gatsby-highlight-code-line\">      <span class=\"token keyword\">const</span> note <span class=\"token operator\">=</span> <span class=\"token function\">get</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span>notes<span class=\"token punctuation\">.</span><span class=\"token function\">find</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">n</span> <span class=\"token operator\">=></span> n<span class=\"token punctuation\">.</span>id <span class=\"token operator\">===</span> id<span class=\"token punctuation\">)</span></span>      <span class=\"token keyword\">const</span> updated <span class=\"token operator\">=</span> <span class=\"token keyword\">await</span> noteService<span class=\"token punctuation\">.</span><span class=\"token function\">update</span><span class=\"token punctuation\">(</span>\n        id<span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span> <span class=\"token operator\">...</span>note<span class=\"token punctuation\">,</span> <span class=\"token literal-property property\">important</span><span class=\"token operator\">:</span> <span class=\"token operator\">!</span>note<span class=\"token punctuation\">.</span>important <span class=\"token punctuation\">}</span>\n      <span class=\"token punctuation\">)</span>\n      <span class=\"token function\">set</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">state</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span>\n        <span class=\"token literal-property property\">notes</span><span class=\"token operator\">:</span> state<span class=\"token punctuation\">.</span>notes<span class=\"token punctuation\">.</span><span class=\"token function\">map</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">n</span> <span class=\"token operator\">=></span> n<span class=\"token punctuation\">.</span>id <span class=\"token operator\">===</span> id <span class=\"token operator\">?</span> updated <span class=\"token operator\">:</span> n<span class=\"token punctuation\">)</span>\n      <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n    <span class=\"token comment\">// ...</span>\n  <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>Funktio <i>get</i> siis palauttaa storen sen hetkisen tilan. Eli esimerkiksi kutsu <i>get().notes</i> antaa storen tämänhetkiset muistiinpanot. Funktio <i>get</i> vastaa toiminnaltaan kutsua <i>useNoteStore.getState()</i>, mutta on idiomattisin tapa viitata storen tilaan storen omien funktioiden sisältä.</p>\n<p>Sovelluksen koodi on <a href=\"https://github.com/fullstack-hy2020/zustand-notes/tree/part6-5\">GitHubissa</a> branchissa <i>part6-5</i>.</p>\n</div>\n<div class=\"tasks\">\n<h3>Tehtävät 6.7.-6.11.</h3>\n<h4>6.7 anekdootit, step6</h4>\n<p>Hae sovelluksen käynnistyessä anekdootit JSON Serverillä toteutetusta backendistä. Käytä HTTP-pyynnön tekemiseen Fetch APIa.</p>\n<p>Backendin alustavan sisällön saat esim. <a href=\"https://github.com/fullstack-hy2020/misc/blob/master/anecdotes.json\">täältä</a>.</p>\n<h4>6.8 anekdootit, step7</h4>\n<p>Muuta uusien anekdoottien luomista siten, että anekdootit talletetaan backendiin. Hyödynnä toteutuksessasi jälleen Fetch APIa.</p>\n<h4>6.9 anekdootit, step8</h4>\n<p>Äänestäminen ei vielä talleta muutoksia backendiin. Korjaa tilanne.</p>\n<h4>6.10 anekdootit, step9</h4>\n<p>Sovelluksessa on valmiina komponentin <i>Notification</i> runko:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token keyword\">const</span> <span class=\"token function-variable function\">Notification</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">const</span> style <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token literal-property property\">border</span><span class=\"token operator\">:</span> <span class=\"token string\">'solid'</span><span class=\"token punctuation\">,</span>\n    <span class=\"token literal-property property\">padding</span><span class=\"token operator\">:</span> <span class=\"token number\">10</span><span class=\"token punctuation\">,</span>\n    <span class=\"token literal-property property\">borderWidth</span><span class=\"token operator\">:</span> <span class=\"token number\">1</span><span class=\"token punctuation\">,</span>\n    <span class=\"token literal-property property\">marginBottom</span><span class=\"token operator\">:</span> <span class=\"token number\">10</span>\n  <span class=\"token punctuation\">}</span>\n\n  <span class=\"token keyword\">return</span> <span class=\"token punctuation\">(</span>\n    <span class=\"token operator\">&lt;</span>div style<span class=\"token operator\">=</span><span class=\"token punctuation\">{</span>style<span class=\"token punctuation\">}</span><span class=\"token operator\">></span>\n      render here notification<span class=\"token operator\">...</span>\n    <span class=\"token operator\">&lt;</span><span class=\"token operator\">/</span>div<span class=\"token operator\">></span>\n  <span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">}</span>\n\n<span class=\"token keyword\">export</span> <span class=\"token keyword\">default</span> Notification</code></pre></div>\n<p>Laajenna sovellusta siten, että se näyttää <i>Notification</i>-komponentin avulla viiden sekunnin ajan, kun sovelluksessa äänestetään tai luodaan uusia anekdootteja:</p>\n<picture><img src=\"/static/c4f460152b68a605ba70ae47ef09301e/5a190/8eb.png\" alt=\"Äänestyksen yhteydessä näytetään notifikaatio: you voted &#x27;if it hurts, do it more often&#x27;\" srcset=\"/static/c4f460152b68a605ba70ae47ef09301e/772e8/8eb.png 200w,\n/static/c4f460152b68a605ba70ae47ef09301e/e17e5/8eb.png 400w,\n/static/c4f460152b68a605ba70ae47ef09301e/5a190/8eb.png 800w,\n/static/c4f460152b68a605ba70ae47ef09301e/35a31/8eb.png 1028w\" sizes=\"(max-width: 800px) 100vw, 800px\"></picture>\n<p>Käytä notifikaation tilanhallintaan Zustandia. Notifikaatioita varten kannattanee tehdä oma Zustand store sillä notifikaation käyttö saattaa liittyä sovelluksen laajentuessa muuhunkin kuin anekdootteihin, esimerkiksi käyttäjän kirjautumiseen.</p>\n<h4>6.11 anekdootit, step10</h4>\n<p>Huomaamme, että osa käyttäjien lisäämistä anekdooteista on huonoja. Toteuta sovellukseen ominaisuus, joka mahdollistaa sellaisten anekdoottien poiston, joilla ei ole yhtään ääntä.</p>\n</div>\n<div class=\"content\">\n<h3>Middlewaret</h3>\n<p>Sovellusta kehittäessä törmää tilanteeseen, jossa on vaikea hahmottaa, miksi sovellus käyttäytyy odottamattomasti. Tila muuttuu jonkun action-funktion seurauksena, mutta on epäselvää, mikä kutsu muutti mitäkin ja missä järjestyksessä. Perinteinen konsolilokitus yksittäisistä funktioista auttaa vain rajallisesti.</p>\n<p>Zustand tukee ns. middlewareja, joiden avulla voidaan lisätä toiminnallisuutta storeihin läpinäkyvästi, ilman että itse storen logiikkaan tarvitsee koskea. Middlewaren idea on yksinkertainen: se \"kietoutuu\" storen ympärille ja voi reagoida jokaiseen tilanmuutoksen automaattisesti halutulla tavalla.</p>\n<p>Middlewarefunktioiden muoto on hieman kryptinen. Seuraavassa on <i>logger</i>, joka tulostaa aina tilan vaihtuessa storen vanhan ja uuden tilan:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token keyword\">const</span> <span class=\"token function-variable function\">logger</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">config</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">set<span class=\"token punctuation\">,</span> <span class=\"token keyword\">get</span></span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token function\">config</span><span class=\"token punctuation\">(</span>\n  <span class=\"token punctuation\">(</span><span class=\"token parameter\"><span class=\"token operator\">...</span>args</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n    console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span><span class=\"token string\">'prev state'</span><span class=\"token punctuation\">,</span> <span class=\"token function\">get</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token function\">set</span><span class=\"token punctuation\">(</span><span class=\"token operator\">...</span>args<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span><span class=\"token string\">'next state'</span><span class=\"token punctuation\">,</span> <span class=\"token function\">get</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n  get\n<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre></div>\n<p>Middleware otetaan käyttöön \"kietomalla\" Zustandin <i>create</i>:lle annettava funktio sen parametriksi:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"gatsby-highlight-code-line\"><span class=\"token keyword\">const</span> useNoteStore <span class=\"token operator\">=</span> <span class=\"token function\">create</span><span class=\"token punctuation\">(</span><span class=\"token function\">logger</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">set<span class=\"token punctuation\">,</span> <span class=\"token keyword\">get</span></span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span></span>  <span class=\"token literal-property property\">notes</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n  <span class=\"token literal-property property\">filter</span><span class=\"token operator\">:</span> <span class=\"token string\">''</span><span class=\"token punctuation\">,</span>\n  <span class=\"token literal-property property\">actions</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token comment\">// ...</span>\n  <span class=\"token punctuation\">}</span>\n<span class=\"gatsby-highlight-code-line\"><span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span></span></code></pre></div>\n<p>Nyt storen tilan muuttuessa näemme konsolista aina miten tila muuttuu:</p>\n<picture><img src=\"/static/b789265b6af129ff09dd51d1fe46259b/5a190/u4.png\" srcset=\"/static/b789265b6af129ff09dd51d1fe46259b/772e8/u4.png 200w,\n/static/b789265b6af129ff09dd51d1fe46259b/e17e5/u4.png 400w,\n/static/b789265b6af129ff09dd51d1fe46259b/5a190/u4.png 800w,\n/static/b789265b6af129ff09dd51d1fe46259b/c1b63/u4.png 1200w,\n/static/b789265b6af129ff09dd51d1fe46259b/29007/u4.png 1600w,\n/static/b789265b6af129ff09dd51d1fe46259b/8d9a9/u4.png 2244w\" sizes=\"(max-width: 800px) 100vw, 800px\"></picture>\n<p>Käytännössä määrittelemämme middleware toimii siten, että se korvaa alkuperäisen funktion <i>set</i> funktiolla </p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\">  <span class=\"token punctuation\">(</span><span class=\"token parameter\"><span class=\"token operator\">...</span>args</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n    console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span><span class=\"token string\">'prev state'</span><span class=\"token punctuation\">,</span> <span class=\"token function\">get</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token function\">set</span><span class=\"token punctuation\">(</span><span class=\"token operator\">...</span>args<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span><span class=\"token string\">'next state'</span><span class=\"token punctuation\">,</span> <span class=\"token function\">get</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span></code></pre></div>\n<p>joka tulostaa vanhan ja uuden tilan (joihin se pääsee käsiksi funktiolla <i>get</i>) konsoliin sen lisäksi että se kutsuu vanhaa funktiota <i>set</i>. Toisena parametrina on vanha <i>get</i> muuttumattomana.</p>\n<p>Zustandissa on myös valmis <i>devtools</i>-middleware, joka integroi storen selaimen <a href=\"https://chromewebstore.google.com/detail/redux-devtools/lmhkpmbekcpmknklioeibfkpmmfibljd\">Redux DevTools</a> -laajennukseen. Devtools on kehitystyökaluna erittäin hyödyllinen, sillä sen avulla voi seurata tilan muutoksia graafisesti.</p>\n<p>Käyttöönotto on helppo tehdä:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token keyword\">import</span> <span class=\"token punctuation\">{</span> create <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">'zustand'</span>\n<span class=\"gatsby-highlight-code-line\"><span class=\"token keyword\">import</span> <span class=\"token punctuation\">{</span> devtools <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">'zustand/middleware'</span></span>\n<span class=\"gatsby-highlight-code-line\"><span class=\"token keyword\">const</span> useNoteStore <span class=\"token operator\">=</span> <span class=\"token function\">create</span><span class=\"token punctuation\">(</span><span class=\"token function\">devtools</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">set<span class=\"token punctuation\">,</span> <span class=\"token keyword\">get</span></span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span></span>  <span class=\"token literal-property property\">notes</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n  <span class=\"token literal-property property\">filter</span><span class=\"token operator\">:</span> <span class=\"token string\">''</span><span class=\"token punctuation\">,</span>\n  <span class=\"token literal-property property\">actions</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token comment\">// ...</span>\n  <span class=\"token punctuation\">}</span>\n<span class=\"gatsby-highlight-code-line\"><span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span></span></code></pre></div>\n<p>Kun Redux DevTools -laajennus on asennettuna selaimeen, voidaan storen tilaa ja sen muutoksia tarkastella selaimen konsolista:</p>\n<picture><img src=\"/static/9d3b0d250c37dab1dd5d32a163cd6035/5a190/u6.png\" alt=\"Redux DevTools -näkymä selaimessa: vasemmalla lista tilan muutoksista, oikealla tilan sisältö puumuodossa\" srcset=\"/static/9d3b0d250c37dab1dd5d32a163cd6035/772e8/u6.png 200w,\n/static/9d3b0d250c37dab1dd5d32a163cd6035/e17e5/u6.png 400w,\n/static/9d3b0d250c37dab1dd5d32a163cd6035/5a190/u6.png 800w,\n/static/9d3b0d250c37dab1dd5d32a163cd6035/c1b63/u6.png 1200w,\n/static/9d3b0d250c37dab1dd5d32a163cd6035/29007/u6.png 1600w,\n/static/9d3b0d250c37dab1dd5d32a163cd6035/d544a/u6.png 1950w\" sizes=\"(max-width: 800px) 100vw, 800px\"></picture>\n<h3>Zustand-storejen testaaminen</h3>\n<p>Tarkastellaan vielä lopuksi Zustand-storejen testaamista Vitestillä.</p>\n<p>Aloitetaan yksinkertaisuuden vuoksi laskurin storesta:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token keyword\">import</span> <span class=\"token punctuation\">{</span> create <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">'zustand'</span>\n\n<span class=\"token keyword\">const</span> useCounterStore <span class=\"token operator\">=</span> <span class=\"token function\">create</span><span class=\"token punctuation\">(</span><span class=\"token parameter\"><span class=\"token keyword\">set</span></span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span>\n  <span class=\"token literal-property property\">counter</span><span class=\"token operator\">:</span> <span class=\"token number\">0</span><span class=\"token punctuation\">,</span>\n  <span class=\"token literal-property property\">actions</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token function-variable function\">increment</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token function\">set</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">state</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">counter</span><span class=\"token operator\">:</span> state<span class=\"token punctuation\">.</span>counter <span class=\"token operator\">+</span> <span class=\"token number\">1</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n    <span class=\"token function-variable function\">decrement</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token function\">set</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">state</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">counter</span><span class=\"token operator\">:</span> state<span class=\"token punctuation\">.</span>counter <span class=\"token operator\">-</span> <span class=\"token number\">1</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n    <span class=\"token function-variable function\">zero</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token function\">set</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">counter</span><span class=\"token operator\">:</span> <span class=\"token number\">0</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n  <span class=\"token punctuation\">}</span>  \n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n\n<span class=\"token keyword\">export</span> <span class=\"token keyword\">const</span> <span class=\"token function-variable function\">useCounter</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token function\">useCounterStore</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">state</span> <span class=\"token operator\">=></span> state<span class=\"token punctuation\">.</span>counter<span class=\"token punctuation\">)</span>\n<span class=\"token keyword\">export</span> <span class=\"token keyword\">const</span> <span class=\"token function-variable function\">useCounterControls</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token function\">useCounterStore</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">state</span> <span class=\"token operator\">=></span> state<span class=\"token punctuation\">.</span>actions<span class=\"token punctuation\">)</span>\n\n<span class=\"gatsby-highlight-code-line\"><span class=\"token keyword\">export</span> <span class=\"token keyword\">default</span> useCounterStore</span></code></pre></div>\n<p>Lisäsimme testejä varten määrittelyyn eksportin, jonka avulla testi pääsee käsiksi storeen.</p>\n<p>Asennetaan Vitest:</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">npm install --save-dev vitest</code></pre></div>\n<p>Toteutetaan testi tiedostoon <i>store.test.js</i>:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token keyword\">import</span> <span class=\"token punctuation\">{</span> beforeEach<span class=\"token punctuation\">,</span> describe<span class=\"token punctuation\">,</span> expect<span class=\"token punctuation\">,</span> it <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">'vitest'</span>\n<span class=\"token keyword\">import</span> useCounterStore <span class=\"token keyword\">from</span> <span class=\"token string\">'./store'</span>\n\n<span class=\"token function\">beforeEach</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n  useCounterStore<span class=\"token punctuation\">.</span><span class=\"token function\">setState</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">counter</span><span class=\"token operator\">:</span> <span class=\"token number\">0</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n\n<span class=\"token function\">describe</span><span class=\"token punctuation\">(</span><span class=\"token string\">'counter store'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n  <span class=\"token function\">it</span><span class=\"token punctuation\">(</span><span class=\"token string\">'initial state is 0'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n    <span class=\"token function\">expect</span><span class=\"token punctuation\">(</span>useCounterStore<span class=\"token punctuation\">.</span><span class=\"token function\">getState</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span>counter<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">toBe</span><span class=\"token punctuation\">(</span><span class=\"token number\">0</span><span class=\"token punctuation\">)</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n\n  <span class=\"token function\">it</span><span class=\"token punctuation\">(</span><span class=\"token string\">'increment increases counter by 1'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n    useCounterStore<span class=\"token punctuation\">.</span><span class=\"token function\">getState</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span>actions<span class=\"token punctuation\">.</span><span class=\"token function\">increment</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n    <span class=\"token function\">expect</span><span class=\"token punctuation\">(</span>useCounterStore<span class=\"token punctuation\">.</span><span class=\"token function\">getState</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span>counter<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">toBe</span><span class=\"token punctuation\">(</span><span class=\"token number\">1</span><span class=\"token punctuation\">)</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n\n  <span class=\"token function\">it</span><span class=\"token punctuation\">(</span><span class=\"token string\">'decrement decreases counter by 1'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n    useCounterStore<span class=\"token punctuation\">.</span><span class=\"token function\">getState</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span>actions<span class=\"token punctuation\">.</span><span class=\"token function\">decrement</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n    <span class=\"token function\">expect</span><span class=\"token punctuation\">(</span>useCounterStore<span class=\"token punctuation\">.</span><span class=\"token function\">getState</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span>counter<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">toBe</span><span class=\"token punctuation\">(</span><span class=\"token operator\">-</span><span class=\"token number\">1</span><span class=\"token punctuation\">)</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n\n  <span class=\"token function\">it</span><span class=\"token punctuation\">(</span><span class=\"token string\">'zero resets counter to 0'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n    useCounterStore<span class=\"token punctuation\">.</span><span class=\"token function\">getState</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span>actions<span class=\"token punctuation\">.</span><span class=\"token function\">increment</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n    useCounterStore<span class=\"token punctuation\">.</span><span class=\"token function\">getState</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span>actions<span class=\"token punctuation\">.</span><span class=\"token function\">increment</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n    useCounterStore<span class=\"token punctuation\">.</span><span class=\"token function\">getState</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span>actions<span class=\"token punctuation\">.</span><span class=\"token function\">zero</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n    <span class=\"token function\">expect</span><span class=\"token punctuation\">(</span>useCounterStore<span class=\"token punctuation\">.</span><span class=\"token function\">getState</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span>counter<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">toBe</span><span class=\"token punctuation\">(</span><span class=\"token number\">0</span><span class=\"token punctuation\">)</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>Testit ovat varsin suoraviivaiset ja hyödyntävät storen funktiota <a href=\"https://zustand.docs.pmnd.rs/reference/apis/create#returns\">getState</a>, joiden avulla ne pääsevät lukemaan storen tilaa sekä suorittamaan storen funktiota.</p>\n<p>Ennen jokaista testiä store palautetaan alkutilaan <i>beforeEach</i>-lohkossa storen funktion <a href=\"https://zustand.docs.pmnd.rs/reference/apis/create#returns\">setState</a> avulla.</p>\n<p>Storen palauttaminen alkutilaan on tapauksessamme yksinkertaista. Aina ei välttämättä näin ole. Zustandin <a href=\"https://zustand.docs.pmnd.rs/learn/guides/testing#vitest\">dokumentaatio</a> neuvoo tavan, miten storeista voidaan luoda testejä varten versio, joka asetetaan automaattisesti alkutilaan ennen jokaista testiä. Tapa on kuitenkin sen verran monimutkainen ja meille tarpeeton, että emme siihen nyt mene.</p>\n<p>Testit siis käyttävät storea suoraan. Jos storejen käyttöön on toteutettu custom hookeina monimutkaisempaa logiikkaa, saattaa olla tarpeen tehdä testit siten, että ne myös hyödyntävät hookkeja.</p>\n<p>Laskurissa storen käyttö tapahtuu hookien <i>useCounter</i> ja <i>useCounterControls</i> kautta:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token keyword\">const</span> useCounterStore <span class=\"token operator\">=</span> <span class=\"token function\">create</span><span class=\"token punctuation\">(</span><span class=\"token parameter\"><span class=\"token keyword\">set</span></span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span>\n  <span class=\"token comment\">// ...</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n\n<span class=\"token comment\">// hightlight-start</span>\n<span class=\"token keyword\">export</span> <span class=\"token keyword\">const</span> <span class=\"token function-variable function\">useCounter</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token function\">useCounterStore</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">state</span> <span class=\"token operator\">=></span> state<span class=\"token punctuation\">.</span>counter<span class=\"token punctuation\">)</span>\n<span class=\"token keyword\">export</span> <span class=\"token keyword\">const</span> <span class=\"token function-variable function\">useCounterControls</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token function\">useCounterStore</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">state</span> <span class=\"token operator\">=></span> state<span class=\"token punctuation\">.</span>actions<span class=\"token punctuation\">)</span>\n<span class=\"token comment\">// hightlight-end</span></code></pre></div>\n<p>Tässä tapauksessa hookit eivät sisällä mitään logiikkaa, ne vaan paljastavat erikseen storen tallettaman arvon ja storen funktiot. Yllä käyttämämme testaustapa on siis oikein hyvä.</p>\n<p>Tehdään kuitenkin esimerkin vuoksi vielä toinen version testeistä, missä storea käytetään täysin samalla tavalla kuin sovellus sitä käyttää.</p>\n<p><i>useCounter</i> ja <i>useCounterControls</i> ovat React hookeja, joten niiden testaamiseen tarvitsemme <a href=\"https://github.com/testing-library/react-testing-library\">React Testing Libraryn</a> sekä <a href=\"https://github.com/jsdom/jsdom\">jsdom</a>-kirjaston:</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">npm install --save-dev @testing-library/react jsdom</code></pre></div>\n<p>Lisätään tiedostoon <i>vite.config.js</i> testausympäristöstä kertova konfiguraatio:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token keyword\">import</span> <span class=\"token punctuation\">{</span> defineConfig <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">'vite'</span>\n<span class=\"token keyword\">import</span> react <span class=\"token keyword\">from</span> <span class=\"token string\">'@vitejs/plugin-react'</span>\n\n<span class=\"token keyword\">export</span> <span class=\"token keyword\">default</span> <span class=\"token function\">defineConfig</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span>\n  <span class=\"token literal-property property\">plugins</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span><span class=\"token function\">react</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n<span class=\"gatsby-highlight-code-line\">  <span class=\"token literal-property property\">test</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span></span><span class=\"gatsby-highlight-code-line\">    <span class=\"token literal-property property\">environment</span><span class=\"token operator\">:</span> <span class=\"token string\">'jsdom'</span><span class=\"token punctuation\">,</span></span><span class=\"gatsby-highlight-code-line\">  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span></span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>Testit ovat seuraavassa:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token keyword\">import</span> <span class=\"token punctuation\">{</span> beforeEach<span class=\"token punctuation\">,</span> describe<span class=\"token punctuation\">,</span> expect<span class=\"token punctuation\">,</span> it <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">'vitest'</span>\n<span class=\"token keyword\">import</span> <span class=\"token punctuation\">{</span> renderHook<span class=\"token punctuation\">,</span> act <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">'@testing-library/react'</span>\n<span class=\"token keyword\">import</span> useCounterStore<span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span> useCounter<span class=\"token punctuation\">,</span> useCounterControls <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">'./store'</span>\n\n<span class=\"token function\">beforeEach</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n  useCounterStore<span class=\"token punctuation\">.</span><span class=\"token function\">setState</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">counter</span><span class=\"token operator\">:</span> <span class=\"token number\">0</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n\n<span class=\"token function\">describe</span><span class=\"token punctuation\">(</span><span class=\"token string\">'counter hooks'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n  <span class=\"token function\">it</span><span class=\"token punctuation\">(</span><span class=\"token string\">'useCounter returns initial value of 0'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">const</span> <span class=\"token punctuation\">{</span> result <span class=\"token punctuation\">}</span> <span class=\"token operator\">=</span> <span class=\"token function\">renderHook</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token function\">useCounter</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n    <span class=\"token function\">expect</span><span class=\"token punctuation\">(</span>result<span class=\"token punctuation\">.</span>current<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">toBe</span><span class=\"token punctuation\">(</span><span class=\"token number\">0</span><span class=\"token punctuation\">)</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n\n  <span class=\"token function\">it</span><span class=\"token punctuation\">(</span><span class=\"token string\">'increment updates counter'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">const</span> <span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">result</span><span class=\"token operator\">:</span> counter <span class=\"token punctuation\">}</span> <span class=\"token operator\">=</span> <span class=\"token function\">renderHook</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token function\">useCounter</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n    <span class=\"token keyword\">const</span> <span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">result</span><span class=\"token operator\">:</span> controls <span class=\"token punctuation\">}</span> <span class=\"token operator\">=</span> <span class=\"token function\">renderHook</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token function\">useCounterControls</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n\n    <span class=\"token function\">act</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> controls<span class=\"token punctuation\">.</span>current<span class=\"token punctuation\">.</span><span class=\"token function\">increment</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n\n    <span class=\"token function\">expect</span><span class=\"token punctuation\">(</span>counter<span class=\"token punctuation\">.</span>current<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">toBe</span><span class=\"token punctuation\">(</span><span class=\"token number\">1</span><span class=\"token punctuation\">)</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n\n  <span class=\"token function\">it</span><span class=\"token punctuation\">(</span><span class=\"token string\">'decrement updates counter'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">const</span> <span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">result</span><span class=\"token operator\">:</span> counter <span class=\"token punctuation\">}</span> <span class=\"token operator\">=</span> <span class=\"token function\">renderHook</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token function\">useCounter</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n    <span class=\"token keyword\">const</span> <span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">result</span><span class=\"token operator\">:</span> controls <span class=\"token punctuation\">}</span> <span class=\"token operator\">=</span> <span class=\"token function\">renderHook</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token function\">useCounterControls</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n\n    <span class=\"token function\">act</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> controls<span class=\"token punctuation\">.</span>current<span class=\"token punctuation\">.</span><span class=\"token function\">decrement</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n\n    <span class=\"token function\">expect</span><span class=\"token punctuation\">(</span>counter<span class=\"token punctuation\">.</span>current<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">toBe</span><span class=\"token punctuation\">(</span><span class=\"token operator\">-</span><span class=\"token number\">1</span><span class=\"token punctuation\">)</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n\n  <span class=\"token function\">it</span><span class=\"token punctuation\">(</span><span class=\"token string\">'zero resets counter'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">const</span> <span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">result</span><span class=\"token operator\">:</span> counter <span class=\"token punctuation\">}</span> <span class=\"token operator\">=</span> <span class=\"token function\">renderHook</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token function\">useCounter</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n    <span class=\"token keyword\">const</span> <span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">result</span><span class=\"token operator\">:</span> controls <span class=\"token punctuation\">}</span> <span class=\"token operator\">=</span> <span class=\"token function\">renderHook</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token function\">useCounterControls</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n\n    <span class=\"token function\">act</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n      controls<span class=\"token punctuation\">.</span>current<span class=\"token punctuation\">.</span><span class=\"token function\">increment</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n      controls<span class=\"token punctuation\">.</span>current<span class=\"token punctuation\">.</span><span class=\"token function\">increment</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n      controls<span class=\"token punctuation\">.</span>current<span class=\"token punctuation\">.</span><span class=\"token function\">zero</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n\n    <span class=\"token function\">expect</span><span class=\"token punctuation\">(</span>counter<span class=\"token punctuation\">.</span>current<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">toBe</span><span class=\"token punctuation\">(</span><span class=\"token number\">0</span><span class=\"token punctuation\">)</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>Testissä on muutama mielenkiintoinen asia. Testien aluksi hookit renderöidään funktion <a href=\"https://testing-library.com/docs/react-testing-library/api/#renderhook\">renderHook</a> avulla:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token keyword\">const</span> <span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">result</span><span class=\"token operator\">:</span> counter <span class=\"token punctuation\">}</span> <span class=\"token operator\">=</span> <span class=\"token function\">renderHook</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token function\">useCounter</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n<span class=\"token keyword\">const</span> <span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">result</span><span class=\"token operator\">:</span> controls <span class=\"token punctuation\">}</span> <span class=\"token operator\">=</span> <span class=\"token function\">renderHook</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token function\">useCounterControls</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>Näin testi pääsee käsiksi hookien palauttamiin funktioihin, jotka sijoitetaan muuttujiin <i>counter</i> ja <i>controls</i>.</p>\n<p>Hookeja kutsutaan wrappaamalla kutsu funktion <a href=\"https://testing-library.com/docs/react-testing-library/api/#act\">act</a> sisälle:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token function\">act</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n  controls<span class=\"token punctuation\">.</span>current<span class=\"token punctuation\">.</span><span class=\"token function\">increment</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n  controls<span class=\"token punctuation\">.</span>current<span class=\"token punctuation\">.</span><span class=\"token function\">increment</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n  controls<span class=\"token punctuation\">.</span>current<span class=\"token punctuation\">.</span><span class=\"token function\">zero</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>Lopuksi tapahtuu testin ekspektaatio:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token function\">expect</span><span class=\"token punctuation\">(</span>counter<span class=\"token punctuation\">.</span>current<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">toBe</span><span class=\"token punctuation\">(</span><span class=\"token number\">0</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>Kuten huomaamme, päästäksemme hookiin itseensä käsiksi joudumme vielä ottamaan funktion <i>renderHook</i> palauttamasta oliosta kentän <i>current</i>, joka vastaa hookin nykyistä arvoa.</p>\n<blockquote>\n<h4>Mikä on act?</h4>\n<p><i>act</i> on apufunktio, joka varmistaa että kaikki tilan päivitykset ja niiden aiheuttamat sivuvaikutukset on käsitelty loppuun ennen kuin testikoodi jatkuu.</p>\n<p>Kun React-komponentissa tai hookissa tapahtuu tilan muutos React ei päivitä tilaa välittömästi vaan jonottaa päivitykset. act pakottaa nämä jonossa olevat päivitykset suoritettaviksi</p>\n<p>Ilman actia testi saattaisi tarkistaa tilan ennen kuin React on ehtinyt päivittää sen, jolloin testi epäonnistuisi tai antaisi väärän tuloksen.</p>\n<p>React Testing Library käärii monet toimintonsa (kuten fireEvent, userEvent) automaattisesti act:iin, mutta hookeja suoraan testattaessa sitä on viisainta käyttää.</p>\n</blockquote>\n<p>Hookien kautta tapahtuva testaaminen käyttää React Testing Libraryä, ja\nrenderöi hookit oikeassa React-kontekstissa jsdomin avulla. Tämä lähestymistapa on huomattavasti hitaampi kuin suoraan storea käyttävät testit, eli jos hookit eivät sisällä kompleksista logiikkaa, voi olla riittävää suorittaa testit suoraan storea käyttäen.</p>\n<p>Zustand-laskurin testit sisältävä koodi löytyy <a href=\"https://github.com/fullstack-hy2020/zustand-counter\">GitHubista</a>.</p>\n<h3>Muistiinpanostoren testaaminen</h3>\n<p>Muistiinpanosovelluksen storen testaaminen on hieman haastavampi tapaus, sillä store sisältää asynkronisia funktioita, jotka kutsuvat palvelinta:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token keyword\">import</span> <span class=\"token punctuation\">{</span> create <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">'zustand'</span>\n<span class=\"token keyword\">import</span> noteService <span class=\"token keyword\">from</span> <span class=\"token string\">'./services/notes'</span>\n\n<span class=\"token keyword\">const</span> useNoteStore <span class=\"token operator\">=</span> <span class=\"token function\">create</span><span class=\"token punctuation\">(</span><span class=\"token parameter\"><span class=\"token keyword\">set</span></span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span>\n  <span class=\"token literal-property property\">notes</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n  <span class=\"token literal-property property\">filter</span><span class=\"token operator\">:</span> <span class=\"token string\">''</span><span class=\"token punctuation\">,</span>\n  <span class=\"token literal-property property\">actions</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token function-variable function\">add</span><span class=\"token operator\">:</span> <span class=\"token keyword\">async</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">content</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n<span class=\"gatsby-highlight-code-line\">      <span class=\"token keyword\">const</span> newNote <span class=\"token operator\">=</span> <span class=\"token keyword\">await</span> noteService<span class=\"token punctuation\">.</span><span class=\"token function\">createNew</span><span class=\"token punctuation\">(</span>content<span class=\"token punctuation\">)</span></span>      <span class=\"token function\">set</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">state</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">notes</span><span class=\"token operator\">:</span> state<span class=\"token punctuation\">.</span>notes<span class=\"token punctuation\">.</span><span class=\"token function\">concat</span><span class=\"token punctuation\">(</span>newNote<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n    <span class=\"token function-variable function\">toggleImportance</span><span class=\"token operator\">:</span> <span class=\"token keyword\">async</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">id</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n      <span class=\"token keyword\">const</span> note <span class=\"token operator\">=</span> useNoteStore<span class=\"token punctuation\">.</span><span class=\"token function\">getState</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span>notes<span class=\"token punctuation\">.</span><span class=\"token function\">find</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">n</span> <span class=\"token operator\">=></span> n<span class=\"token punctuation\">.</span>id <span class=\"token operator\">===</span> id<span class=\"token punctuation\">)</span>\n<span class=\"gatsby-highlight-code-line\">      <span class=\"token keyword\">const</span> updated <span class=\"token operator\">=</span> <span class=\"token keyword\">await</span> noteService<span class=\"token punctuation\">.</span><span class=\"token function\">update</span><span class=\"token punctuation\">(</span></span><span class=\"gatsby-highlight-code-line\">        id<span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span> <span class=\"token operator\">...</span>note<span class=\"token punctuation\">,</span> <span class=\"token literal-property property\">important</span><span class=\"token operator\">:</span> <span class=\"token operator\">!</span>note<span class=\"token punctuation\">.</span>important <span class=\"token punctuation\">}</span></span><span class=\"gatsby-highlight-code-line\">      <span class=\"token punctuation\">)</span></span>      <span class=\"token function\">set</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">state</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span>\n        <span class=\"token literal-property property\">notes</span><span class=\"token operator\">:</span> state<span class=\"token punctuation\">.</span>notes<span class=\"token punctuation\">.</span><span class=\"token function\">map</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">n</span> <span class=\"token operator\">=></span> n<span class=\"token punctuation\">.</span>id <span class=\"token operator\">===</span> id <span class=\"token operator\">?</span> updated <span class=\"token operator\">:</span> n<span class=\"token punctuation\">)</span>\n      <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n    <span class=\"token function-variable function\">setFilter</span><span class=\"token operator\">:</span> <span class=\"token parameter\">value</span> <span class=\"token operator\">=></span> <span class=\"token function\">set</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">filter</span><span class=\"token operator\">:</span> value <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n    <span class=\"token function-variable function\">initialize</span><span class=\"token operator\">:</span> <span class=\"token keyword\">async</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n<span class=\"gatsby-highlight-code-line\">      <span class=\"token keyword\">const</span> notes <span class=\"token operator\">=</span> <span class=\"token keyword\">await</span> noteService<span class=\"token punctuation\">.</span><span class=\"token function\">getAll</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></span>      <span class=\"token function\">set</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span> notes <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">}</span>\n  <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n\n<span class=\"token keyword\">export</span> <span class=\"token keyword\">const</span> <span class=\"token function-variable function\">useNotes</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span> \n  <span class=\"token keyword\">const</span> notes <span class=\"token operator\">=</span> <span class=\"token function\">useNoteStore</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">state</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> state<span class=\"token punctuation\">.</span>notes<span class=\"token punctuation\">)</span>\n  <span class=\"token keyword\">const</span> filter <span class=\"token operator\">=</span> <span class=\"token function\">useNoteStore</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">state</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> state<span class=\"token punctuation\">.</span>filter<span class=\"token punctuation\">)</span>\n\n  <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>filter <span class=\"token operator\">===</span> <span class=\"token string\">'important'</span><span class=\"token punctuation\">)</span> <span class=\"token keyword\">return</span> notes<span class=\"token punctuation\">.</span><span class=\"token function\">filter</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">n</span> <span class=\"token operator\">=></span> n<span class=\"token punctuation\">.</span>important<span class=\"token punctuation\">)</span>\n  <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>filter <span class=\"token operator\">===</span> <span class=\"token string\">'nonimportant'</span><span class=\"token punctuation\">)</span> <span class=\"token keyword\">return</span> notes<span class=\"token punctuation\">.</span><span class=\"token function\">filter</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">n</span> <span class=\"token operator\">=></span> <span class=\"token operator\">!</span>n<span class=\"token punctuation\">.</span>important<span class=\"token punctuation\">)</span>\n  <span class=\"token keyword\">return</span> notes\n<span class=\"token punctuation\">}</span>\n\n<span class=\"token keyword\">export</span> <span class=\"token keyword\">const</span> <span class=\"token function-variable function\">useFilter</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token function\">useNoteStore</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">state</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> state<span class=\"token punctuation\">.</span>filter<span class=\"token punctuation\">)</span>\n<span class=\"token keyword\">export</span> <span class=\"token keyword\">const</span> <span class=\"token function-variable function\">useNoteActions</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token function\">useNoteStore</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">state</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> state<span class=\"token punctuation\">.</span>actions<span class=\"token punctuation\">)</span></code></pre></div>\n<p>Tällä kertaa myös <i>useNotes</i> sisältää merkittävissä määrin logiikkaa, joten testaus lienee syytä tehdä hookien kautta React Testing Libraryllä.</p>\n<p>Asennetaan tarvittavat kirjastot:</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">npm install --save-dev vitest @testing-library/react jsdom</code></pre></div>\n<p>Lisätään tiedostoon <i>vite.config.js</i> testausympäristöstä kertova konfiguraatio:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token keyword\">import</span> <span class=\"token punctuation\">{</span> defineConfig <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">'vite'</span>\n<span class=\"token keyword\">import</span> react <span class=\"token keyword\">from</span> <span class=\"token string\">'@vitejs/plugin-react'</span>\n\n<span class=\"token keyword\">export</span> <span class=\"token keyword\">default</span> <span class=\"token function\">defineConfig</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span>\n  <span class=\"token literal-property property\">plugins</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span><span class=\"token function\">react</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n<span class=\"gatsby-highlight-code-line\">  <span class=\"token literal-property property\">test</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span></span><span class=\"gatsby-highlight-code-line\">    <span class=\"token literal-property property\">environment</span><span class=\"token operator\">:</span> <span class=\"token string\">'jsdom'</span><span class=\"token punctuation\">,</span></span><span class=\"gatsby-highlight-code-line\">  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span></span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>Testien ensimmäinen osa seuraavassa:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token keyword\">import</span> <span class=\"token punctuation\">{</span> describe<span class=\"token punctuation\">,</span> it<span class=\"token punctuation\">,</span> expect<span class=\"token punctuation\">,</span> beforeEach<span class=\"token punctuation\">,</span> vi <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">'vitest'</span>\n<span class=\"token keyword\">import</span> <span class=\"token punctuation\">{</span> renderHook<span class=\"token punctuation\">,</span> act <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">'@testing-library/react'</span>\n\nvi<span class=\"token punctuation\">.</span><span class=\"token function\">mock</span><span class=\"token punctuation\">(</span><span class=\"token string\">'./services/notes'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">default</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token literal-property property\">getAll</span><span class=\"token operator\">:</span> vi<span class=\"token punctuation\">.</span><span class=\"token function\">fn</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n    <span class=\"token literal-property property\">createNew</span><span class=\"token operator\">:</span> vi<span class=\"token punctuation\">.</span><span class=\"token function\">fn</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n    <span class=\"token literal-property property\">update</span><span class=\"token operator\">:</span> vi<span class=\"token punctuation\">.</span><span class=\"token function\">fn</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n  <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n\n<span class=\"token keyword\">import</span> noteService <span class=\"token keyword\">from</span> <span class=\"token string\">'./services/notes'</span>\n<span class=\"token keyword\">import</span> useNoteStore<span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span> useNotes<span class=\"token punctuation\">,</span> useFilter<span class=\"token punctuation\">,</span> useNoteActions <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">'./store'</span>\n\n<span class=\"token function\">beforeEach</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n  useNoteStore<span class=\"token punctuation\">.</span><span class=\"token function\">setState</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">notes</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span> <span class=\"token literal-property property\">filter</span><span class=\"token operator\">:</span> <span class=\"token string\">''</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n  vi<span class=\"token punctuation\">.</span><span class=\"token function\">clearAllMocks</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n\n<span class=\"token function\">describe</span><span class=\"token punctuation\">(</span><span class=\"token string\">'useNoteActions'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n  <span class=\"token function\">it</span><span class=\"token punctuation\">(</span><span class=\"token string\">'initialize loads notes from service'</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">async</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">const</span> mockNotes <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">id</span><span class=\"token operator\">:</span> <span class=\"token number\">1</span><span class=\"token punctuation\">,</span> <span class=\"token literal-property property\">content</span><span class=\"token operator\">:</span> <span class=\"token string\">'Test'</span><span class=\"token punctuation\">,</span> <span class=\"token literal-property property\">important</span><span class=\"token operator\">:</span> <span class=\"token boolean\">false</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">]</span>\n    noteService<span class=\"token punctuation\">.</span>getAll<span class=\"token punctuation\">.</span><span class=\"token function\">mockResolvedValue</span><span class=\"token punctuation\">(</span>mockNotes<span class=\"token punctuation\">)</span>\n\n    <span class=\"token keyword\">const</span> <span class=\"token punctuation\">{</span> result <span class=\"token punctuation\">}</span> <span class=\"token operator\">=</span> <span class=\"token function\">renderHook</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token function\">useNoteActions</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n\n    <span class=\"token keyword\">await</span> <span class=\"token function\">act</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">async</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n      <span class=\"token keyword\">await</span> result<span class=\"token punctuation\">.</span>current<span class=\"token punctuation\">.</span><span class=\"token function\">initialize</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n\n    <span class=\"token keyword\">const</span> <span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">result</span><span class=\"token operator\">:</span> notesResult <span class=\"token punctuation\">}</span> <span class=\"token operator\">=</span> <span class=\"token function\">renderHook</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token function\">useNotes</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n    <span class=\"token function\">expect</span><span class=\"token punctuation\">(</span>notesResult<span class=\"token punctuation\">.</span>current<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">toEqual</span><span class=\"token punctuation\">(</span>mockNotes<span class=\"token punctuation\">)</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n\n  <span class=\"token function\">it</span><span class=\"token punctuation\">(</span><span class=\"token string\">'add appends a new note'</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">async</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">const</span> newNote <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">id</span><span class=\"token operator\">:</span> <span class=\"token number\">2</span><span class=\"token punctuation\">,</span> <span class=\"token literal-property property\">content</span><span class=\"token operator\">:</span> <span class=\"token string\">'New note'</span><span class=\"token punctuation\">,</span> <span class=\"token literal-property property\">important</span><span class=\"token operator\">:</span> <span class=\"token boolean\">false</span> <span class=\"token punctuation\">}</span>\n    noteService<span class=\"token punctuation\">.</span>createNew<span class=\"token punctuation\">.</span><span class=\"token function\">mockResolvedValue</span><span class=\"token punctuation\">(</span>newNote<span class=\"token punctuation\">)</span>\n\n    <span class=\"token keyword\">const</span> <span class=\"token punctuation\">{</span> result <span class=\"token punctuation\">}</span> <span class=\"token operator\">=</span> <span class=\"token function\">renderHook</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token function\">useNoteActions</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n\n    <span class=\"token keyword\">await</span> <span class=\"token function\">act</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">async</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n      <span class=\"token keyword\">await</span> result<span class=\"token punctuation\">.</span>current<span class=\"token punctuation\">.</span><span class=\"token function\">add</span><span class=\"token punctuation\">(</span><span class=\"token string\">'New note'</span><span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n\n    <span class=\"token keyword\">const</span> <span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">result</span><span class=\"token operator\">:</span> notesResult <span class=\"token punctuation\">}</span> <span class=\"token operator\">=</span> <span class=\"token function\">renderHook</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token function\">useNotes</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n    <span class=\"token function\">expect</span><span class=\"token punctuation\">(</span>notesResult<span class=\"token punctuation\">.</span>current<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">toContainEqual</span><span class=\"token punctuation\">(</span>newNote<span class=\"token punctuation\">)</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n\n  <span class=\"token function\">it</span><span class=\"token punctuation\">(</span><span class=\"token string\">'toggleImportance flips important flag'</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">async</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">const</span> note <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">id</span><span class=\"token operator\">:</span> <span class=\"token number\">1</span><span class=\"token punctuation\">,</span> <span class=\"token literal-property property\">content</span><span class=\"token operator\">:</span> <span class=\"token string\">'Test'</span><span class=\"token punctuation\">,</span> <span class=\"token literal-property property\">important</span><span class=\"token operator\">:</span> <span class=\"token boolean\">false</span> <span class=\"token punctuation\">}</span>\n    useNoteStore<span class=\"token punctuation\">.</span><span class=\"token function\">setState</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">notes</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span>note<span class=\"token punctuation\">]</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n    noteService<span class=\"token punctuation\">.</span>update<span class=\"token punctuation\">.</span><span class=\"token function\">mockResolvedValue</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span> <span class=\"token operator\">...</span>note<span class=\"token punctuation\">,</span> <span class=\"token literal-property property\">important</span><span class=\"token operator\">:</span> <span class=\"token boolean\">true</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n\n    <span class=\"token keyword\">const</span> <span class=\"token punctuation\">{</span> result <span class=\"token punctuation\">}</span> <span class=\"token operator\">=</span> <span class=\"token function\">renderHook</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token function\">useNoteActions</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n\n    <span class=\"token keyword\">await</span> <span class=\"token function\">act</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">async</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n      <span class=\"token keyword\">await</span> result<span class=\"token punctuation\">.</span>current<span class=\"token punctuation\">.</span><span class=\"token function\">toggleImportance</span><span class=\"token punctuation\">(</span><span class=\"token number\">1</span><span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n\n    <span class=\"token keyword\">const</span> <span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">result</span><span class=\"token operator\">:</span> notesResult <span class=\"token punctuation\">}</span> <span class=\"token operator\">=</span> <span class=\"token function\">renderHook</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token function\">useNotes</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n    <span class=\"token function\">expect</span><span class=\"token punctuation\">(</span>notesResult<span class=\"token punctuation\">.</span>current<span class=\"token punctuation\">[</span><span class=\"token number\">0</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">.</span>important<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">toBe</span><span class=\"token punctuation\">(</span><span class=\"token boolean\">true</span><span class=\"token punctuation\">)</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>Testeissä on paljon pureskeltavaa. Testit muodostavat Vitestin avulla <a href=\"https://vitest.dev/guide/mocking\">mock</a>-version palvelimen kanssa kommunikoinnista huolehtivasta <i>noteServicestä</i>:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token keyword\">import</span> <span class=\"token punctuation\">{</span> describe<span class=\"token punctuation\">,</span> it<span class=\"token punctuation\">,</span> expect<span class=\"token punctuation\">,</span> beforeEach<span class=\"token punctuation\">,</span> vi <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">'vitest'</span>\n\nvi<span class=\"token punctuation\">.</span><span class=\"token function\">mock</span><span class=\"token punctuation\">(</span><span class=\"token string\">'./services/notes'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">default</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token literal-property property\">getAll</span><span class=\"token operator\">:</span> vi<span class=\"token punctuation\">.</span><span class=\"token function\">fn</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n    <span class=\"token literal-property property\">createNew</span><span class=\"token operator\">:</span> vi<span class=\"token punctuation\">.</span><span class=\"token function\">fn</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n    <span class=\"token literal-property property\">update</span><span class=\"token operator\">:</span> vi<span class=\"token punctuation\">.</span><span class=\"token function\">fn</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n  <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p><a href=\"https://vitest.dev/api/vi.html#vi-mock\">vi.mock</a> korvaa hakemiston <i>./services/notes</i> sisältävän <i>noteServicen</i> omalla versiollaan, missä kaikki funktiot on korvattu <a href=\"https://vitest.dev/api/vi.html#vi-fn\">vi.fn</a> palauttamalla mock-funktiolla.</p>\n<p>Ennen jokaista testiä store palautetaan alkutilaan ja mock-funktiot nollataan:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token function\">beforeEach</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n  useNoteStore<span class=\"token punctuation\">.</span><span class=\"token function\">setState</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">notes</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span> <span class=\"token literal-property property\">filter</span><span class=\"token operator\">:</span> <span class=\"token string\">''</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n  vi<span class=\"token punctuation\">.</span><span class=\"token function\">clearAllMocks</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>Jokaisen testin alussa mockatulle <i>noteServicelle</i> kerrotaan funktion <a href=\"https://vitest.dev/api/mock.html#mockresolvedvalue\">mockResolvedValue</a> avulla kuinka sen tulee toimia testin kontekstissa:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token function\">it</span><span class=\"token punctuation\">(</span><span class=\"token string\">'initialize loads notes from service'</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">async</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n<span class=\"gatsby-highlight-code-line\">  <span class=\"token keyword\">const</span> mockNotes <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">id</span><span class=\"token operator\">:</span> <span class=\"token number\">1</span><span class=\"token punctuation\">,</span> <span class=\"token literal-property property\">content</span><span class=\"token operator\">:</span> <span class=\"token string\">'Test'</span><span class=\"token punctuation\">,</span> <span class=\"token literal-property property\">important</span><span class=\"token operator\">:</span> <span class=\"token boolean\">false</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">]</span></span><span class=\"gatsby-highlight-code-line\">  noteService<span class=\"token punctuation\">.</span>getAll<span class=\"token punctuation\">.</span><span class=\"token function\">mockResolvedValue</span><span class=\"token punctuation\">(</span>mockNotes<span class=\"token punctuation\">)</span></span>\n  <span class=\"token keyword\">const</span> <span class=\"token punctuation\">{</span> result <span class=\"token punctuation\">}</span> <span class=\"token operator\">=</span> <span class=\"token function\">renderHook</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token function\">useNoteActions</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n\n  <span class=\"token keyword\">await</span> <span class=\"token function\">act</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">async</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">await</span> result<span class=\"token punctuation\">.</span>current<span class=\"token punctuation\">.</span><span class=\"token function\">initialize</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n\n  <span class=\"token keyword\">const</span> <span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">result</span><span class=\"token operator\">:</span> notesResult <span class=\"token punctuation\">}</span> <span class=\"token operator\">=</span> <span class=\"token function\">renderHook</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token function\">useNotes</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n  <span class=\"token function\">expect</span><span class=\"token punctuation\">(</span>notesResult<span class=\"token punctuation\">.</span>current<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">toEqual</span><span class=\"token punctuation\">(</span>mockNotes<span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>Aluksi testi siis määrittelee, että kutsuttaessa funktiota <i>noteService.getAll</i> palautetaan storelle taulukossa <i>mockNotes</i> olevat muistiinpanot.</p>\n<p>Testattava asia on funktion <i>initialize</i> kutsu:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token keyword\">await</span> <span class=\"token function\">act</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">async</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">await</span> result<span class=\"token punctuation\">.</span>current<span class=\"token punctuation\">.</span><span class=\"token function\">initialize</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>Koska kyse on asynkronisesta funktiosta, tulee kutsun valmistumista odottaa avainsanaa <i>await</i> käyttämällä. </p>\n<p>Lopuksi testi varmistaa, että storen tilassa on sama lista muistiinpanoja, mitä mockattu  <i>noteService.getAll</i> palautti:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token keyword\">const</span> <span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">result</span><span class=\"token operator\">:</span> notesResult <span class=\"token punctuation\">}</span> <span class=\"token operator\">=</span> <span class=\"token function\">renderHook</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token function\">useNotes</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n<span class=\"token function\">expect</span><span class=\"token punctuation\">(</span>notesResult<span class=\"token punctuation\">.</span>current<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">toEqual</span><span class=\"token punctuation\">(</span>mockNotes<span class=\"token punctuation\">)</span></code></pre></div>\n<p>Muut testit noudattavat samaa kaavaa: ensin määritellään mitä storen kutsuma <i>noteServicen</i> funktio palauttaa, ja tämän jälkeen suoritetaan itse testi.</p>\n<p>Testien jälkimmäinen osa varmistaa filtteröinnin toimivuuden:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token function\">describe</span><span class=\"token punctuation\">(</span><span class=\"token string\">'useNotes filtering'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">const</span> notes <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span>\n    <span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">id</span><span class=\"token operator\">:</span> <span class=\"token number\">1</span><span class=\"token punctuation\">,</span> <span class=\"token literal-property property\">content</span><span class=\"token operator\">:</span> <span class=\"token string\">'A'</span><span class=\"token punctuation\">,</span> <span class=\"token literal-property property\">important</span><span class=\"token operator\">:</span> <span class=\"token boolean\">true</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n    <span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">id</span><span class=\"token operator\">:</span> <span class=\"token number\">2</span><span class=\"token punctuation\">,</span> <span class=\"token literal-property property\">content</span><span class=\"token operator\">:</span> <span class=\"token string\">'B'</span><span class=\"token punctuation\">,</span> <span class=\"token literal-property property\">important</span><span class=\"token operator\">:</span> <span class=\"token boolean\">false</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n  <span class=\"token punctuation\">]</span>\n\n  <span class=\"token function\">beforeEach</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n    useNoteStore<span class=\"token punctuation\">.</span><span class=\"token function\">setState</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span> notes <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n\n  <span class=\"token function\">it</span><span class=\"token punctuation\">(</span><span class=\"token string\">'returns all notes with no filter'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">const</span> <span class=\"token punctuation\">{</span> result <span class=\"token punctuation\">}</span> <span class=\"token operator\">=</span> <span class=\"token function\">renderHook</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token function\">useNotes</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n    <span class=\"token function\">expect</span><span class=\"token punctuation\">(</span>result<span class=\"token punctuation\">.</span>current<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">toHaveLength</span><span class=\"token punctuation\">(</span><span class=\"token number\">2</span><span class=\"token punctuation\">)</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n\n  <span class=\"token function\">it</span><span class=\"token punctuation\">(</span><span class=\"token string\">'filters important notes'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n    useNoteStore<span class=\"token punctuation\">.</span><span class=\"token function\">setState</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span> notes<span class=\"token punctuation\">,</span> <span class=\"token literal-property property\">filter</span><span class=\"token operator\">:</span> <span class=\"token string\">'important'</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n    <span class=\"token keyword\">const</span> <span class=\"token punctuation\">{</span> result <span class=\"token punctuation\">}</span> <span class=\"token operator\">=</span> <span class=\"token function\">renderHook</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token function\">useNotes</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n    <span class=\"token function\">expect</span><span class=\"token punctuation\">(</span>result<span class=\"token punctuation\">.</span>current<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">toEqual</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">[</span>notes<span class=\"token punctuation\">[</span><span class=\"token number\">0</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n\n  <span class=\"token function\">it</span><span class=\"token punctuation\">(</span><span class=\"token string\">'filters nonimportant notes'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n    useNoteStore<span class=\"token punctuation\">.</span><span class=\"token function\">setState</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span> notes<span class=\"token punctuation\">,</span> <span class=\"token literal-property property\">filter</span><span class=\"token operator\">:</span> <span class=\"token string\">'nonimportant'</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n    <span class=\"token keyword\">const</span> <span class=\"token punctuation\">{</span> result <span class=\"token punctuation\">}</span> <span class=\"token operator\">=</span> <span class=\"token function\">renderHook</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token function\">useNotes</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n    <span class=\"token function\">expect</span><span class=\"token punctuation\">(</span>result<span class=\"token punctuation\">.</span>current<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">toEqual</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">[</span>notes<span class=\"token punctuation\">[</span><span class=\"token number\">1</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>Tila alustetaan kahdella muistiinpanolla, joista toinen on tärkeä ja toinen ei. Kolme testitapausta tarkastavat, että <i>useNotes</i> palauttaa kaikilla filtterin arvoilla oikeat muistiinpanot.</p>\n<p>Sovelluksen lopullinen koodi on <a href=\"https://github.com/fullstack-hy2020/zustand-notes/tree/part6-6\">GitHubissa</a> branchissa <i>part6-6</i>.</p>\n</div>\n<div class=\"tasks\">\n<h3>Tehtävät 6.12.-6.15.</h3>\n<h4>6.12 anekdootit, step11</h4>\n<p>Tee testi, joka varmistaa, että tila alustetaan niillä anekdooteilla, jotka backend palauttaa.</p>\n<h4>6.13 anekdootit, step12</h4>\n<p>Tee testi, joka varmistaa että anekdootit näyttävä komponentti saa anekdootit storelta äänten mukaan järjestettynä</p>\n<h4>6.14 anekdootit, step13</h4>\n<p>Tee testi, joka varmistaa, että oikea React-komponentti saa oikein filtteröidyn listan anekdooteista.</p>\n<h4>6.15 anekdootit, step14</h4>\n<p>Tee testi, joka varmistaa, että äänestäminen korottaa anekdootin äänien määrää.</p>\n</div>","frontmatter":{"mainImage":{"publicURL":"/static/a3b7bc3fafcb5b47227616e1343970e5/part-6.svg"},"part":6,"letter":"b","lang":"fi"}}},"pageContext":{"part":6,"letter":"b","lang":"fi"}},"staticQueryHashes":["3128451518"]}