{"componentChunkName":"component---src-templates-content-template-js","path":"/es/part6/react_query_y_context_api","result":{"data":{"markdownRemark":{"html":"<div class=\"content\">\n<p>Al final de esta parte, analizaremos algunas formas diferentes de administrar el estado de una aplicación.</p>\n<p>Continuemos con la aplicación de notas. Nos centraremos en la comunicación con el servidor. Comencemos la aplicación desde cero. La primera versión es la siguiente:</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 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\">event</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n    event<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> event<span class=\"token punctuation\">.</span>target<span class=\"token punctuation\">.</span>note<span class=\"token punctuation\">.</span>value\n    event<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    console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>content<span class=\"token punctuation\">)</span>\n  <span class=\"token punctuation\">}</span>\n\n  <span class=\"token keyword\">const</span> <span class=\"token function-variable function\">toggleImportance</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">note</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\">'toggle importance of'</span><span class=\"token punctuation\">,</span> note<span class=\"token punctuation\">.</span>id<span class=\"token punctuation\">)</span>\n  <span class=\"token punctuation\">}</span>\n\n  <span class=\"token keyword\">const</span> notes <span class=\"token operator\">=</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>h2<span class=\"token operator\">></span>Notes app<span class=\"token operator\">&lt;</span><span class=\"token operator\">/</span>h2<span class=\"token operator\">></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>notes<span class=\"token punctuation\">.</span><span class=\"token function\">map</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">note</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">(</span>\n        <span class=\"token operator\">&lt;</span>li key<span class=\"token operator\">=</span><span class=\"token punctuation\">{</span>note<span class=\"token punctuation\">.</span>id<span class=\"token punctuation\">}</span> onClick<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\">toggleImportance</span><span class=\"token punctuation\">(</span>note<span class=\"token punctuation\">)</span><span class=\"token punctuation\">}</span><span class=\"token operator\">></span>\n          <span class=\"token punctuation\">{</span>note<span class=\"token punctuation\">.</span>important <span class=\"token operator\">?</span> <span class=\"token operator\">&lt;</span>strong<span class=\"token operator\">></span><span class=\"token punctuation\">{</span>note<span class=\"token punctuation\">.</span>content<span class=\"token punctuation\">}</span><span class=\"token operator\">&lt;</span><span class=\"token operator\">/</span>strong<span class=\"token operator\">></span> <span class=\"token operator\">:</span> note<span class=\"token punctuation\">.</span>content<span class=\"token punctuation\">}</span>\n          <span class=\"token operator\">&lt;</span>button onClick<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\">toggleImportance</span><span class=\"token punctuation\">(</span>note<span class=\"token punctuation\">.</span>id<span class=\"token punctuation\">)</span><span class=\"token punctuation\">}</span><span class=\"token operator\">></span>\n            <span class=\"token punctuation\">{</span>note<span class=\"token punctuation\">.</span>important <span class=\"token operator\">?</span> <span class=\"token string\">'make not important'</span> <span class=\"token operator\">:</span> <span class=\"token string\">'make important'</span><span class=\"token punctuation\">}</span>\n          <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>li<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>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> App</code></pre></div>\n<p>El código inicial está en GitHub en este <a href=\"https://github.com/fullstack-hy2020/query-notes/tree/part6-0\">repositorio</a>, en la rama <i>part6-0</i>.</p>\n<h3>Gestión de datos del servidor con la librería TanStack Query</h3>\n<p>Ahora utilizaremos la librería <a href=\"https://tanstack.com/query/latest\">TanStack Query</a> para almacenar y gestionar los datos obtenidos del servidor.</p>\n<p>Instala la librería con el comando</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> @tanstack/react-query</code></pre></div>\n<p>Se necesitan agregar algunas cosas en el archivo <i>main.jsx</i> para pasar las funciones de la librería a toda la aplicación:</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> createRoot <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">'react-dom/client'</span>\n<span class=\"gatsby-highlight-code-line\"><span class=\"token keyword\">import</span> <span class=\"token punctuation\">{</span> QueryClient<span class=\"token punctuation\">,</span> QueryClientProvider <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">'@tanstack/react-query'</span></span>\n<span class=\"token keyword\">import</span> App <span class=\"token keyword\">from</span> <span class=\"token string\">'./App.jsx'</span>\n\n<span class=\"gatsby-highlight-code-line\"><span class=\"token keyword\">const</span> queryClient <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">QueryClient</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></span>\n<span class=\"token function\">createRoot</span><span class=\"token punctuation\">(</span>document<span class=\"token punctuation\">.</span><span class=\"token function\">getElementById</span><span class=\"token punctuation\">(</span><span class=\"token string\">'root'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">render</span><span class=\"token punctuation\">(</span>\n<span class=\"gatsby-highlight-code-line\">  <span class=\"token operator\">&lt;</span>QueryClientProvider client<span class=\"token operator\">=</span><span class=\"token punctuation\">{</span>queryClient<span class=\"token punctuation\">}</span><span class=\"token operator\">></span></span>    <span class=\"token operator\">&lt;</span>App <span class=\"token operator\">/</span><span class=\"token operator\">></span>\n<span class=\"gatsby-highlight-code-line\">  <span class=\"token operator\">&lt;</span><span class=\"token operator\">/</span>QueryClientProvider<span class=\"token operator\">></span></span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>Usemos <a href=\"https://github.com/typicode/json-server\">JSON Server</a> como en las partes anteriores para simular el backend. JSON Server está preconfigurado en el proyecto de ejemplo, y la raíz del proyecto contiene un archivo <i>db.json</i> que por defecto tiene dos notas. Puedes iniciar el servidor con:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\">npm run server</code></pre></div>\n<p>Ahora podemos recuperar las notas en el componente <i>App</i>. El código se expande de la siguiente manera:</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\">import</span> <span class=\"token punctuation\">{</span> useQuery <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">'@tanstack/react-query'</span></span>\n<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 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\">event</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n    event<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> event<span class=\"token punctuation\">.</span>target<span class=\"token punctuation\">.</span>note<span class=\"token punctuation\">.</span>value\n    event<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    console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>content<span class=\"token punctuation\">)</span>\n  <span class=\"token punctuation\">}</span>\n\n  <span class=\"token keyword\">const</span> <span class=\"token function-variable function\">toggleImportance</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">note</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\">'toggle importance of'</span><span class=\"token punctuation\">,</span> note<span class=\"token punctuation\">.</span>id<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> result <span class=\"token operator\">=</span> <span class=\"token function\">useQuery</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span></span><span class=\"gatsby-highlight-code-line\">    <span class=\"token literal-property property\">queryKey</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span><span class=\"token string\">'notes'</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span></span><span class=\"gatsby-highlight-code-line\">    <span class=\"token function-variable function\">queryFn</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> 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 string\">'http://localhost:3001/notes'</span><span class=\"token punctuation\">)</span></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 fetch notes'</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 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><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\">  console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span><span class=\"token constant\">JSON</span><span class=\"token punctuation\">.</span><span class=\"token function\">parse</span><span class=\"token punctuation\">(</span><span class=\"token constant\">JSON</span><span class=\"token punctuation\">.</span><span class=\"token function\">stringify</span><span class=\"token punctuation\">(</span>result<span class=\"token punctuation\">)</span><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>result<span class=\"token punctuation\">.</span>isPending<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span></span><span class=\"gatsby-highlight-code-line\">    <span class=\"token keyword\">return</span> <span class=\"token operator\">&lt;</span>div<span class=\"token operator\">></span>loading data<span class=\"token operator\">...</span><span class=\"token operator\">&lt;</span><span class=\"token operator\">/</span>div<span class=\"token operator\">></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> notes <span class=\"token operator\">=</span> result<span class=\"token punctuation\">.</span>data</span>\n  <span class=\"token keyword\">return</span> <span class=\"token punctuation\">(</span>\n    <span class=\"token comment\">// ...</span>\n  <span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>La obtención de datos del servidor se realiza, como en el capítulo anterior, usando el método <i>fetch</i> de la Fetch API. Sin embargo, la llamada al método ahora está envuelta en una <a href=\"https://tanstack.com/query/latest/docs/react/guides/queries\">query</a> (consulta) formada con la función <a href=\"https://tanstack.com/query/latest/docs/react/reference/useQuery\">useQuery</a>. La llamada a <i>useQuery</i> toma como parámetro un objeto con los campos <i>queryKey</i> y <i>queryFn</i>. El valor del campo <i>queryKey</i> es un array que contiene el string <i>notes</i>. Actúa como la <a href=\"https://tanstack.com/query/latest/docs/react/guides/query-keys\">clave</a> para la query definida, es decir, la lista de notas.</p>\n<p>El valor devuelto por la función <i>useQuery</i> es un objeto que indica el estado de la query. La salida a la consola ilustra la situación:</p>\n<picture><img src=\"/static/eca4cfcb02caac965004ac5d5b6364db/5a190/t3.png\" alt=\"consola del navegador mostrando el estado success\" srcset=\"/static/eca4cfcb02caac965004ac5d5b6364db/772e8/t3.png 200w,\n/static/eca4cfcb02caac965004ac5d5b6364db/e17e5/t3.png 400w,\n/static/eca4cfcb02caac965004ac5d5b6364db/5a190/t3.png 800w,\n/static/eca4cfcb02caac965004ac5d5b6364db/c1b63/t3.png 1200w,\n/static/eca4cfcb02caac965004ac5d5b6364db/29007/t3.png 1600w,\n/static/eca4cfcb02caac965004ac5d5b6364db/96191/t3.png 2176w\" sizes=\"(max-width: 800px) 100vw, 800px\"></picture>\n<p>Es decir, la primera vez que se renderiza el componente, la query todavía está en estado <i>loading</i>, es decir, la solicitud HTTP asociada está pendiente. En esta etapa, solo se procesa lo siguiente:</p>\n<div class=\"gatsby-highlight\" data-language=\"html\"><pre class=\"language-html\"><code class=\"language-html\"><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>div</span><span class=\"token punctuation\">></span></span>loading data...<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>div</span><span class=\"token punctuation\">></span></span></code></pre></div>\n<p>Sin embargo, la solicitud HTTP se completa tan rápido que ni siquiera Max Verstappen podría ver el texto. Cuando se completa la solicitud, el componente se renderiza de nuevo. La query está en el estado <i>success</i> en la segunda renderización, y el campo <i>data</i> del objeto de la query contiene los datos devueltos por la solicitud, es decir, la lista de notas que se muestran en la pantalla.</p>\n<p>Entonces, la aplicación recupera datos del servidor y los renderiza en la pantalla sin usar los Hooks de React <i>useState</i> y <i>useEffect</i> utilizados en los capítulos 2-5. Los datos en el servidor ahora están completamente bajo la administración de la librería TanStack Query, ¡y la aplicación no necesita el estado definido con el Hook de React <i>useState</i> en absoluto!</p>\n<p>Movamos la función que realiza la solicitud HTTP a su propio archivo <i>src/requests.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\">export</span> <span class=\"token keyword\">const</span> <span class=\"token function-variable function\">getNotes</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  <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  <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>El componente <i>App</i> ahora se ha simplificado un poco:</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> useQuery <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">'@tanstack/react-query'</span> \n<span class=\"gatsby-highlight-code-line\"><span class=\"token keyword\">import</span> <span class=\"token punctuation\">{</span> getNotes <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">'./requests'</span></span>\n<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 comment\">// ...</span>\n\n  <span class=\"token keyword\">const</span> result <span class=\"token operator\">=</span> <span class=\"token function\">useQuery</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span>\n    <span class=\"token literal-property property\">queryKey</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span><span class=\"token string\">'notes'</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n<span class=\"gatsby-highlight-code-line\">    <span class=\"token literal-property property\">queryFn</span><span class=\"token operator\">:</span> getNotes</span>  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n\n  <span class=\"token comment\">// ...</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>El código actual de la aplicación está en <a href=\"https://github.com/fullstack-hy2020/query-notes/tree/part6-1\">GitHub</a> en la rama <i>part6-1</i>.</p>\n<h3>Sincronización de datos con el servidor mediante TanStack Query</h3>\n<p>Los datos ya se han recuperado correctamente del servidor. A continuación, nos aseguraremos de que los datos agregados y modificados se almacenen en el servidor. Comencemos agregando nuevas notas.</p>\n<p>Hagamos una función <i>createNote</i> en el archivo <i>requests.js</i> para guardar nuevas notas:</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\">export</span> <span class=\"token keyword\">const</span> <span class=\"token function-variable function\">getNotes</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  <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  <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\">export</span> <span class=\"token keyword\">const</span> <span class=\"token function-variable function\">createNote</span> <span class=\"token operator\">=</span> <span class=\"token keyword\">async</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">newNote</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> 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>newNote<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><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></code></pre></div>\n<p>El componente <i>App</i> cambiará de la siguiente manera</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\">import</span> <span class=\"token punctuation\">{</span> useQuery<span class=\"token punctuation\">,</span> useMutation <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">'@tanstack/react-query'</span></span><span class=\"gatsby-highlight-code-line\"><span class=\"token keyword\">import</span> <span class=\"token punctuation\">{</span> getNotes<span class=\"token punctuation\">,</span> createNote <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">'./requests'</span></span>\n<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> newNoteMutation <span class=\"token operator\">=</span> <span class=\"token function\">useMutation</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span></span><span class=\"gatsby-highlight-code-line\">    <span class=\"token literal-property property\">mutationFn</span><span class=\"token operator\">:</span> createNote<span class=\"token punctuation\">,</span></span><span class=\"gatsby-highlight-code-line\">  <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\">event</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n    event<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> event<span class=\"token punctuation\">.</span>target<span class=\"token punctuation\">.</span>note<span class=\"token punctuation\">.</span>value\n    event<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=\"gatsby-highlight-code-line\">    newNoteMutation<span class=\"token punctuation\">.</span><span class=\"token function\">mutate</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\">true</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span></span>  <span class=\"token punctuation\">}</span>\n\n  <span class=\"token comment\">//</span>\n\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>Para crear una nueva nota, se define una <a href=\"https://tanstack.com/query/latest/docs/react/guides/mutations\">mutación</a> usando la función <a href=\"https://tanstack.com/query/latest/docs/react/reference/useMutation\">useMutation</a>:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token keyword\">const</span> newNoteMutation <span class=\"token operator\">=</span> <span class=\"token function\">useMutation</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span>\n  <span class=\"token literal-property property\">mutationFn</span><span class=\"token operator\">:</span> createNote<span class=\"token punctuation\">,</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>El parámetro es la función que agregamos al archivo <i>requests.js</i>, que usa la Fetch API para enviar una nueva nota al servidor.</p>\n<p>El controlador de eventos <i>addNote</i> realiza la mutación llamando a la función <i>mutate</i> del objeto de mutación y pasando la nueva nota como parámetro:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\">newNoteMutation<span class=\"token punctuation\">.</span><span class=\"token function\">mutate</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\">true</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>Nuestra solución es buena. Excepto que no funciona. La nueva nota se guarda en el servidor, pero no se actualiza en la pantalla.</p>\n<p>Para renderizar una nueva nota también, debemos decirle a TanStack Query que el resultado antiguo de la query cuya clave es el string <i>notes</i> debe ser <a href=\"https://tanstack.com/query/latest/docs/react/guides/invalidations-from-mutations\">invalidado</a>.</p>\n<p>Afortunadamente, la invalidación es fácil, se puede hacer definiendo la función de callback <i>onSuccess</i> apropiada para la mutación:</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\">import</span> <span class=\"token punctuation\">{</span> useQuery<span class=\"token punctuation\">,</span> useMutation<span class=\"token punctuation\">,</span> useQueryClient <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">'@tanstack/react-query'</span></span><span class=\"token keyword\">import</span> <span class=\"token punctuation\">{</span> getNotes<span class=\"token punctuation\">,</span> createNote <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">'./requests'</span>\n\n<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> queryClient <span class=\"token operator\">=</span> <span class=\"token function\">useQueryClient</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></span>\n  <span class=\"token keyword\">const</span> newNoteMutation <span class=\"token operator\">=</span> <span class=\"token function\">useMutation</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span>\n    <span class=\"token literal-property property\">mutationFn</span><span class=\"token operator\">:</span> createNote<span class=\"token punctuation\">,</span>\n<span class=\"gatsby-highlight-code-line\">    <span class=\"token function-variable function\">onSuccess</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\">      queryClient<span class=\"token punctuation\">.</span><span class=\"token function\">invalidateQueries</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">queryKey</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span><span class=\"token string\">'notes'</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=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n\n  <span class=\"token comment\">// ...</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>Ahora que la mutación se ha ejecutado con éxito, se realiza una llamada a la función</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\">queryClient<span class=\"token punctuation\">.</span><span class=\"token function\">invalidateQueries</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">queryKey</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span><span class=\"token string\">'notes'</span><span class=\"token punctuation\">]</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>Esto a su vez hace que TanStack Query actualice automáticamente una query con la clave <i>notes</i>, es decir, obtenga las notas del servidor. Como resultado, la aplicación renderiza el estado actualizado en el servidor, es decir, la nota agregada también se renderiza.</p>\n<p>Implementemos también el cambio en la importancia de las notas. Se agrega una función para actualizar notas al archivo <i>requests.js</i>:</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\">updateNote</span> <span class=\"token operator\">=</span> <span class=\"token keyword\">async</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">updatedNote</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">const</span> options <span class=\"token operator\">=</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>updatedNote<span class=\"token punctuation\">)</span>\n  <span class=\"token punctuation\">}</span>\n\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>updatedNote<span class=\"token punctuation\">.</span>id<span class=\"token interpolation-punctuation punctuation\">}</span></span><span class=\"token template-punctuation string\">`</span></span><span class=\"token punctuation\">,</span> options<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></code></pre></div>\n<p>Actualizar la nota también se hace mediante una mutación. El componente <i>App</i> se expande de la siguiente manera:</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> useQuery<span class=\"token punctuation\">,</span> useMutation<span class=\"token punctuation\">,</span> useQueryClient <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">'@tanstack/react-query'</span>\n<span class=\"gatsby-highlight-code-line\"><span class=\"token keyword\">import</span> <span class=\"token punctuation\">{</span> getNotes<span class=\"token punctuation\">,</span> createNote<span class=\"token punctuation\">,</span> updateNote <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">'./requests'</span></span>\n<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> queryClient <span class=\"token operator\">=</span> <span class=\"token function\">useQueryClient</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n\n  <span class=\"token keyword\">const</span> newNoteMutation <span class=\"token operator\">=</span> <span class=\"token function\">useMutation</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span>\n    <span class=\"token literal-property property\">mutationFn</span><span class=\"token operator\">:</span> createNote<span class=\"token punctuation\">,</span>\n    <span class=\"token function-variable function\">onSuccess</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      queryClient<span class=\"token punctuation\">.</span><span class=\"token function\">invalidateQueries</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">queryKey</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span><span class=\"token string\">'notes'</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>\n\n<span class=\"gatsby-highlight-code-line\">  <span class=\"token keyword\">const</span> updateNoteMutation <span class=\"token operator\">=</span> <span class=\"token function\">useMutation</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span></span><span class=\"gatsby-highlight-code-line\">    <span class=\"token literal-property property\">mutationFn</span><span class=\"token operator\">:</span> updateNote<span class=\"token punctuation\">,</span></span><span class=\"gatsby-highlight-code-line\">    <span class=\"token function-variable function\">onSuccess</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\">      queryClient<span class=\"token punctuation\">.</span><span class=\"token function\">invalidateQueries</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">queryKey</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span><span class=\"token string\">'notes'</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 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\">event</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n    event<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> event<span class=\"token punctuation\">.</span>target<span class=\"token punctuation\">.</span>note<span class=\"token punctuation\">.</span>value\n    event<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    newNoteMutation<span class=\"token punctuation\">.</span><span class=\"token function\">mutate</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\">true</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n  <span class=\"token punctuation\">}</span>\n\n  <span class=\"token keyword\">const</span> <span class=\"token function-variable function\">toggleImportance</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">note</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n<span class=\"gatsby-highlight-code-line\">    updateNoteMutation<span class=\"token punctuation\">.</span><span class=\"token function\">mutate</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 operator\">!</span>note<span class=\"token punctuation\">.</span>important <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span></span>  <span class=\"token punctuation\">}</span>\n\n  <span class=\"token comment\">// ...</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>De nuevo, se creó una mutación que invalidó la query <i>notes</i> para que la nota actualizada se renderice correctamente. Usar mutaciones es fácil, el método <i>mutate</i> recibe una nota como parámetro, cuya importancia se cambia a la negación del valor antiguo.</p>\n<p>El código actual de la aplicación está en <a href=\"https://github.com/fullstack-hy2020/query-notes/tree/part6-2\">GitHub</a> en la rama <i>part6-2</i>.</p>\n<h3>Optimizando el rendimiento</h3>\n<p>La aplicación funciona bien y el código es relativamente simple. La facilidad para realizar cambios en la lista de notas es particularmente sorprendente. Por ejemplo, cuando cambiamos la importancia de una nota, invalidar la query <i>notes</i> es suficiente para que los datos de la aplicación se actualicen:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token keyword\">const</span> updateNoteMutation <span class=\"token operator\">=</span> <span class=\"token function\">useMutation</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span>\n  <span class=\"token literal-property property\">mutationFn</span><span class=\"token operator\">:</span> updateNote<span class=\"token punctuation\">,</span>\n  <span class=\"token function-variable function\">onSuccess</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\">    queryClient<span class=\"token punctuation\">.</span><span class=\"token function\">invalidateQueries</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">queryKey</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span><span class=\"token string\">'notes'</span><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></code></pre></div>\n<p>La consecuencia de esto, por supuesto, es que después de la solicitud PUT que causa el cambio de nota, la aplicación realiza una nueva solicitud GET para recuperar los datos de la query desde el servidor:</p>\n<picture><img src=\"/static/53b62ff1f2517f0e7b8a3b4bd45ffe77/5a190/t4.png\" alt=\"pestaña de red con las solicitudes 3 y notes resaltadas\" srcset=\"/static/53b62ff1f2517f0e7b8a3b4bd45ffe77/772e8/t4.png 200w,\n/static/53b62ff1f2517f0e7b8a3b4bd45ffe77/e17e5/t4.png 400w,\n/static/53b62ff1f2517f0e7b8a3b4bd45ffe77/5a190/t4.png 800w,\n/static/53b62ff1f2517f0e7b8a3b4bd45ffe77/c1b63/t4.png 1200w,\n/static/53b62ff1f2517f0e7b8a3b4bd45ffe77/29007/t4.png 1600w,\n/static/53b62ff1f2517f0e7b8a3b4bd45ffe77/e431d/t4.png 1882w\" sizes=\"(max-width: 800px) 100vw, 800px\"></picture>\n<p>Si la cantidad de datos obtenidos por la aplicación no es grande, realmente no importa. Después de todo, desde el punto de vista de la funcionalidad del lado del navegador, hacer una solicitud HTTP GET adicional realmente no importa, pero en algunas situaciones podría generar una carga en el servidor.</p>\n<p>Si fuera necesario, es posible también <a href=\"https://tanstack.com/query/latest/docs/react/guides/updates-from-mutation-responses\">optimizar el rendimiento manualmente</a>, actualizando el estado de la query mantenido por TanStack Query.</p>\n<p>El cambio para la mutación que agrega una nueva nota es el siguiente:</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> queryClient <span class=\"token operator\">=</span> <span class=\"token function\">useQueryClient</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n\n  <span class=\"token keyword\">const</span> newNoteMutation <span class=\"token operator\">=</span> <span class=\"token function\">useMutation</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span>\n    <span class=\"token literal-property property\">mutationFn</span><span class=\"token operator\">:</span> createNote<span class=\"token punctuation\">,</span>\n<span class=\"gatsby-highlight-code-line\">    <span class=\"token function-variable function\">onSuccess</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">newNote</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> queryClient<span class=\"token punctuation\">.</span><span class=\"token function\">getQueryData</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">[</span><span class=\"token string\">'notes'</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span></span><span class=\"gatsby-highlight-code-line\">      queryClient<span class=\"token punctuation\">.</span><span class=\"token function\">setQueryData</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">[</span><span class=\"token string\">'notes'</span><span class=\"token punctuation\">]</span><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>    <span class=\"token punctuation\">}</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n\n  <span class=\"token comment\">// ...</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>Es decir, en el callback de <i>onSuccess</i>, el objeto <i>queryClient</i> primero lee el estado existente de <i>notes</i> de la query y lo actualiza agregando una nueva nota, que se obtiene como parámetro de la función de callback. El valor del parámetro es el valor devuelto por la función <i>createNote</i>, definida en el archivo <i>requests.js</i> de la siguiente manera:</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\">createNote</span> <span class=\"token operator\">=</span> <span class=\"token keyword\">async</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">newNote</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">const</span> options <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token literal-property property\">method</span><span class=\"token operator\">:</span> <span class=\"token string\">'POST'</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>newNote<span class=\"token punctuation\">)</span>\n  <span class=\"token punctuation\">}</span>\n\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> options<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 create note'</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>Sería relativamente fácil hacer un cambio similar a una mutación que cambia la importancia de la nota, pero lo dejamos como un ejercicio opcional.</p>\n<p>Finalmente, nota un detalle interesante. TanStack Query vuelve a obtener todas las notas cuando cambiamos a otra pestaña del navegador y luego regresamos a la pestaña de la aplicación. Esto se puede observar en la pestaña de Red de la Consola de Desarrollador:</p>\n<picture><img src=\"/static/5d6cd2bffdf3fb2457abe08821630c50/5a190/t5.png\" alt=\"aplicación de notas y solicitud notes con estado 200 en la pestaña de red\" srcset=\"/static/5d6cd2bffdf3fb2457abe08821630c50/772e8/t5.png 200w,\n/static/5d6cd2bffdf3fb2457abe08821630c50/e17e5/t5.png 400w,\n/static/5d6cd2bffdf3fb2457abe08821630c50/5a190/t5.png 800w,\n/static/5d6cd2bffdf3fb2457abe08821630c50/c1b63/t5.png 1200w,\n/static/5d6cd2bffdf3fb2457abe08821630c50/29007/t5.png 1600w,\n/static/5d6cd2bffdf3fb2457abe08821630c50/da952/t5.png 1872w\" sizes=\"(max-width: 800px) 100vw, 800px\"></picture>\n<p>¿Qué está pasando? Al leer la <a href=\"https://tanstack.com/query/latest/docs/react/reference/useQuery\">documentación</a>, nos damos cuenta de que la funcionalidad predeterminada de las queries de TanStack Query es que las queries (cuyo estado es <i>stale</i>) se actualicen cuando cambia el <i>window focus</i>. Si queremos, podemos desactivar la funcionalidad creando una consulta de la siguiente manera:</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 comment\">// ...</span>\n  <span class=\"token keyword\">const</span> result <span class=\"token operator\">=</span> <span class=\"token function\">useQuery</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span>\n    <span class=\"token literal-property property\">queryKey</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span><span class=\"token string\">'notes'</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n    <span class=\"token literal-property property\">queryFn</span><span class=\"token operator\">:</span> getNotes<span class=\"token punctuation\">,</span>\n<span class=\"gatsby-highlight-code-line\">    <span class=\"token literal-property property\">refetchOnWindowFocus</span><span class=\"token operator\">:</span> <span class=\"token boolean\">false</span></span>  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n\n  <span class=\"token comment\">// ...</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>Si colocas un console.log en el código, podrás ver desde la consola del navegador cuántas veces TanStack Query hace que la aplicación se vuelva a renderizar. La regla general es que el renderizado ocurre al menos cada vez que es necesario, es decir, cuando cambia el estado de la query. Puedes leer más al respecto por ejemplo <a href=\"https://tkdodo.eu/blog/react-query-render-optimizations\">aquí</a>.</p>\n<h3>Hook personalizado useNotes</h3>\n<p>Nuestra solución es bastante buena, pero resulta algo incómodo que muchos detalles de implementación de TanStack Query estén directamente en el componente de React. Extraigámoslos a un hook personalizado:</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> useQuery<span class=\"token punctuation\">,</span> useMutation<span class=\"token punctuation\">,</span> useQueryClient <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">'@tanstack/react-query'</span>\n<span class=\"token keyword\">import</span> <span class=\"token punctuation\">{</span> getNotes<span class=\"token punctuation\">,</span> createNote<span class=\"token punctuation\">,</span> updateNote <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">'../requests'</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> queryClient <span class=\"token operator\">=</span> <span class=\"token function\">useQueryClient</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n\n  <span class=\"token keyword\">const</span> result <span class=\"token operator\">=</span> <span class=\"token function\">useQuery</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span>\n    <span class=\"token literal-property property\">queryKey</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span><span class=\"token string\">'notes'</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n    <span class=\"token literal-property property\">queryFn</span><span class=\"token operator\">:</span> getNotes<span class=\"token punctuation\">,</span>\n    <span class=\"token literal-property property\">refetchOnWindowFocus</span><span class=\"token operator\">:</span> <span class=\"token boolean\">false</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n\n  <span class=\"token keyword\">const</span> newNoteMutation <span class=\"token operator\">=</span> <span class=\"token function\">useMutation</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span>\n    <span class=\"token literal-property property\">mutationFn</span><span class=\"token operator\">:</span> createNote<span class=\"token punctuation\">,</span>\n    <span class=\"token function-variable function\">onSuccess</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">newNote</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> queryClient<span class=\"token punctuation\">.</span><span class=\"token function\">getQueryData</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">[</span><span class=\"token string\">'notes'</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span>\n      queryClient<span class=\"token punctuation\">.</span><span class=\"token function\">setQueryData</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">[</span><span class=\"token string\">'notes'</span><span class=\"token punctuation\">]</span><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>\n    <span class=\"token punctuation\">}</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n\n  <span class=\"token keyword\">const</span> updateNoteMutation <span class=\"token operator\">=</span> <span class=\"token function\">useMutation</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span>\n    <span class=\"token literal-property property\">mutationFn</span><span class=\"token operator\">:</span> updateNote<span class=\"token punctuation\">,</span>\n    <span class=\"token function-variable function\">onSuccess</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      queryClient<span class=\"token punctuation\">.</span><span class=\"token function\">invalidateQueries</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">queryKey</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span><span class=\"token string\">'notes'</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>\n\n  <span class=\"token keyword\">return</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token literal-property property\">notes</span><span class=\"token operator\">:</span> result<span class=\"token punctuation\">.</span>data<span class=\"token punctuation\">,</span>\n    <span class=\"token literal-property property\">isPending</span><span class=\"token operator\">:</span> result<span class=\"token punctuation\">.</span>isPending<span class=\"token punctuation\">,</span>\n    <span class=\"token function-variable function\">addNote</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">content</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> newNoteMutation<span class=\"token punctuation\">.</span><span class=\"token function\">mutate</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\">true</span> <span class=\"token punctuation\">}</span><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 punctuation\">(</span><span class=\"token parameter\">note</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> updateNoteMutation<span class=\"token punctuation\">.</span><span class=\"token function\">mutate</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span> \n      <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 \n    <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></code></pre></div>\n<p>El hook encapsula todo el código relacionado con TanStack Query: la query que obtiene las notas y las dos mutaciones que las crean y actualizan. Estos detalles quedan ocultos para quien utiliza el hook, ya que la función devuelve un objeto sencillo con:</p>\n<ul>\n<li><i>notes</i>: la lista de notas</li>\n<li><i>isPending</i>: indica si los datos siguen cargándose</li>\n<li><i>addNote</i>: una función para añadir una nota a partir de su contenido</li>\n<li><i>toggleImportance</i>: una función para cambiar la importancia de una nota</li>\n</ul>\n<p>El componente <i>App</i> se simplifica considerablemente:</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\">'./hooks/useNotes'</span>\n\n<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> notes<span class=\"token punctuation\">,</span> isPending<span class=\"token punctuation\">,</span> <span class=\"token literal-property property\">addNote</span><span class=\"token operator\">:</span> addNoteToServer<span class=\"token punctuation\">,</span> toggleImportance <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>\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\">event</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n    event<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> event<span class=\"token punctuation\">.</span>target<span class=\"token punctuation\">.</span>note<span class=\"token punctuation\">.</span>value\n    event<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 function\">addNoteToServer</span><span class=\"token punctuation\">(</span>content<span class=\"token punctuation\">)</span>\n  <span class=\"token punctuation\">}</span>\n\n  <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>isPending<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">return</span> <span class=\"token operator\">&lt;</span>div<span class=\"token operator\">></span>loading data<span class=\"token operator\">...</span><span class=\"token operator\">&lt;</span><span class=\"token operator\">/</span>div<span class=\"token operator\">></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<span class=\"token operator\">></span>\n      <span class=\"token operator\">&lt;</span>h2<span class=\"token operator\">></span>Notes app<span class=\"token operator\">&lt;</span><span class=\"token operator\">/</span>h2<span class=\"token operator\">></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>notes<span class=\"token punctuation\">.</span><span class=\"token function\">map</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">note</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">(</span>\n        <span class=\"token operator\">&lt;</span>li key<span class=\"token operator\">=</span><span class=\"token punctuation\">{</span>note<span class=\"token punctuation\">.</span>id<span class=\"token punctuation\">}</span><span class=\"token operator\">></span>\n          <span class=\"token punctuation\">{</span>note<span class=\"token punctuation\">.</span>important <span class=\"token operator\">?</span> <span class=\"token operator\">&lt;</span>strong<span class=\"token operator\">></span><span class=\"token punctuation\">{</span>note<span class=\"token punctuation\">.</span>content<span class=\"token punctuation\">}</span><span class=\"token operator\">&lt;</span><span class=\"token operator\">/</span>strong<span class=\"token operator\">></span> <span class=\"token operator\">:</span> note<span class=\"token punctuation\">.</span>content<span class=\"token punctuation\">}</span>\n          <span class=\"token operator\">&lt;</span>button onClick<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\">toggleImportance</span><span class=\"token punctuation\">(</span>note<span class=\"token punctuation\">)</span><span class=\"token punctuation\">}</span><span class=\"token operator\">></span>\n            <span class=\"token punctuation\">{</span>note<span class=\"token punctuation\">.</span>important <span class=\"token operator\">?</span> <span class=\"token string\">'make not important'</span> <span class=\"token operator\">:</span> <span class=\"token string\">'make important'</span><span class=\"token punctuation\">}</span>\n          <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>li<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>div<span class=\"token operator\">></span>\n  <span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>El código de la aplicación está en <a href=\"https://github.com/fullstack-hy2020/query-notes/tree/part6-3\">GitHub</a> en la rama <i>part6-3</i>.</p>\n<p>TanStack Query es una librería versátil que, basándonos en lo que ya hemos visto, simplifica la aplicación. ¿Hace TanStack Query que soluciones de gestión de estado más complejas como Redux sean innecesarias? No. TanStack Query puede reemplazar parcialmente el estado de la aplicación en algunos casos, pero como lo indica la <a href=\"https://tanstack.com/query/latest/docs/react/guides/does-this-replace-client-state\">documentación</a>:</p>\n<ul>\n<li>TanStack Query es una <i>librería de estado del servidor</i>, responsable de la gestión de operaciones asíncronas entre el servidor y el cliente</li>\n<li>Zustand y otras soluciones similares son <i>librerías de estado del cliente</i> que pueden almacenar datos asíncronos, aunque con menor eficiencia que una herramienta como TanStack Query</li>\n</ul>\n<p>Entonces, TanStack Query es una librería que mantiene el <i>estado del servidor</i> en el frontend, es decir, actúa como una caché para lo que se almacena en el servidor. TanStack Query simplifica el procesamiento de datos en el servidor y, en algunos casos, puede eliminar la necesidad de que los datos en el servidor se guarden en el estado del frontend.</p>\n<p>La mayoría de las aplicaciones de React no necesitan solo una forma de almacenar temporalmente los datos servidos, sino también alguna solución para cómo se maneja el resto del estado del frontend (por ejemplo, el estado de los formularios o las notificaciones).</p>\n</div>\n<div class=\"tasks\">\n<h3>Ejercicios 6.16.-6.19.</h3>\n<p>Ahora hagamos una nueva versión de la aplicación de anécdotas que use la librería TanStack Query. Usa <a href=\"https://github.com/fullstack-hy2020/query-anecdotes\">este proyecto</a> como punto de partida. El proyecto tiene un JSON Server instalado, la operación del cual se ha modificado ligeramente (Revisa el archivo <em>server.js</em> para más detalles. Asegúrate de estar conectándote al <em>PORT</em> correcto). Inicia el servidor con <i>npm run server</i>.</p>\n<p>Usa la Fetch API para hacer las peticiones.</p>\n<h4>Ejercicio 6.16</h4>\n<p>Implementa la obtención de anécdotas del servidor usando TanStack Query.</p>\n<p>La aplicación debe funcionar de tal manera que si hay problemas para comunicarse con el servidor, solo se mostrará una página de error:</p>\n<picture><img src=\"/static/457e9cc4c44344cfb7b546caa44f9ef2/5a190/65new.png\" alt=\"navegador diciendo que anecdote service no esta disponible debido a problemas con el servidor en localhost\" srcset=\"/static/457e9cc4c44344cfb7b546caa44f9ef2/772e8/65new.png 200w,\n/static/457e9cc4c44344cfb7b546caa44f9ef2/e17e5/65new.png 400w,\n/static/457e9cc4c44344cfb7b546caa44f9ef2/5a190/65new.png 800w\" sizes=\"(max-width: 800px) 100vw, 800px\"></picture>\n<p>Puedes encontrar <a href=\"https://tanstack.com/query/latest/docs/react/guides/queries\">aquí</a> información sobre cómo detectar posibles errores.</p>\n<p>Puedes simular un problema con el servidor apagando el JSON Server. Ten en cuenta que en una situación problemática, la consulta primero está en el estado <i>isLoading</i> durante un tiempo, porque si una solicitud falla, TanStack Query intenta la solicitud varias veces antes de que indique que la solicitud no es exitosa. Opcionalmente, puedes especificar que no se realicen reintentos:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token keyword\">const</span> result <span class=\"token operator\">=</span> <span class=\"token function\">useQuery</span><span class=\"token punctuation\">(</span>\n  <span class=\"token punctuation\">{</span>\n    <span class=\"token literal-property property\">queryKey</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span><span class=\"token string\">'anecdotes'</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n    <span class=\"token literal-property property\">queryFn</span><span class=\"token operator\">:</span> getAnecdotes<span class=\"token punctuation\">,</span>\n    <span class=\"token literal-property property\">retry</span><span class=\"token operator\">:</span> <span class=\"token boolean\">false</span>\n  <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">)</span></code></pre></div>\n<p>o que la solicitud se vuelva a intentar solo una vez más:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token keyword\">const</span> result <span class=\"token operator\">=</span> <span class=\"token function\">useQuery</span><span class=\"token punctuation\">(</span>\n  <span class=\"token punctuation\">{</span>\n    <span class=\"token literal-property property\">queryKey</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span><span class=\"token string\">'anecdotes'</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n    <span class=\"token literal-property property\">queryFn</span><span class=\"token operator\">:</span> getAnecdotes<span class=\"token punctuation\">,</span>\n    <span class=\"token literal-property property\">retry</span><span class=\"token operator\">:</span> <span class=\"token number\">1</span>\n  <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">)</span></code></pre></div>\n<h4>Ejercicio 6.17</h4>\n<p>Implementa la adición de nuevas anécdotas al servidor usando TanStack Query. La aplicación debe renderizar una nueva anécdota por defecto. Ten en cuenta que el contenido de la anécdota debe tener al menos 5 caracteres de longitud, de lo contrario el servidor rechazará la solicitud POST. No tienes que preocuparte por el control de errores ahora.</p>\n<h4>Ejercicio 6.18</h4>\n<p>Implementa la votación de anécdotas usando nuevamente TanStack Query. La aplicación debe renderizar automáticamente el número aumentado de votos para la anécdota votada.</p>\n<h4>Ejercicio 6.19</h4>\n<p>Extrae los detalles de TanStack Query a un hook personalizado.</p>\n</div>\n<div class=\"content\">\n<h3>Context API</h3>\n<p>Volvamos a la conocida aplicación de contador. La aplicación se define de la siguiente manera:</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> useState <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">'react'</span>\n<span class=\"token keyword\">import</span> Display <span class=\"token keyword\">from</span> <span class=\"token string\">'./components/Display'</span>\n<span class=\"token keyword\">import</span> Controls <span class=\"token keyword\">from</span> <span class=\"token string\">'./components/Controls'</span>\n\n<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>counter<span class=\"token punctuation\">,</span> setCounter<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token function\">useState</span><span class=\"token punctuation\">(</span><span class=\"token number\">0</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>Display counter<span class=\"token operator\">=</span><span class=\"token punctuation\">{</span>counter<span class=\"token punctuation\">}</span> <span class=\"token operator\">/</span><span class=\"token operator\">></span>\n      <span class=\"token operator\">&lt;</span>Controls counter<span class=\"token operator\">=</span><span class=\"token punctuation\">{</span>counter<span class=\"token punctuation\">}</span> setCounter<span class=\"token operator\">=</span><span class=\"token punctuation\">{</span>setCounter<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></code></pre></div>\n<p>El componente <i>App</i> define el estado de la aplicación y se lo pasa a <i>Display</i>, que renderiza el valor del contador:</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\">Display</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\"><span class=\"token punctuation\">{</span> counter <span class=\"token punctuation\">}</span></span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></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><span class=\"token punctuation\">{</span>counter<span class=\"token punctuation\">}</span><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>y al componente <i>Controls</i>, que renderiza los botones:</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\">Controls</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\"><span class=\"token punctuation\">{</span> counter<span class=\"token punctuation\">,</span> setCounter <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\">const</span> <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\">setCounter</span><span class=\"token punctuation\">(</span>counter <span class=\"token operator\">+</span> <span class=\"token number\">1</span><span class=\"token punctuation\">)</span>\n  <span class=\"token keyword\">const</span> <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\">setCounter</span><span class=\"token punctuation\">(</span>counter <span class=\"token operator\">-</span> <span class=\"token number\">1</span><span class=\"token punctuation\">)</span>\n  <span class=\"token keyword\">const</span> <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\">setCounter</span><span class=\"token punctuation\">(</span><span class=\"token number\">0</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>button onClick<span class=\"token operator\">=</span><span class=\"token punctuation\">{</span>increment<span class=\"token punctuation\">}</span><span class=\"token operator\">></span>plus<span class=\"token operator\">&lt;</span><span class=\"token operator\">/</span>button<span class=\"token operator\">></span>\n      <span class=\"token operator\">&lt;</span>button onClick<span class=\"token operator\">=</span><span class=\"token punctuation\">{</span>decrement<span class=\"token punctuation\">}</span><span class=\"token operator\">></span>minus<span class=\"token operator\">&lt;</span><span class=\"token operator\">/</span>button<span class=\"token operator\">></span>\n      <span class=\"token operator\">&lt;</span>button onClick<span class=\"token operator\">=</span><span class=\"token punctuation\">{</span>zero<span class=\"token punctuation\">}</span><span class=\"token operator\">></span>zero<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>div<span class=\"token operator\">></span>\n  <span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>La aplicación crece:</p>\n<picture><img src=\"/static/5ab66ebde93c51016891fa04ed43d28c/5a190/t6.png\" srcset=\"/static/5ab66ebde93c51016891fa04ed43d28c/772e8/t6.png 200w,\n/static/5ab66ebde93c51016891fa04ed43d28c/e17e5/t6.png 400w,\n/static/5ab66ebde93c51016891fa04ed43d28c/5a190/t6.png 800w,\n/static/5ab66ebde93c51016891fa04ed43d28c/c1b63/t6.png 1200w,\n/static/5ab66ebde93c51016891fa04ed43d28c/7a18f/t6.png 1284w\" sizes=\"(max-width: 800px) 100vw, 800px\"></picture>\n<p>El papel de <i>App</i> cambia: sigue conservando el estado, pero ya no renderiza directamente los componentes que lo utilizan:</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>counter<span class=\"token punctuation\">,</span> setCounter<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token function\">useState</span><span class=\"token punctuation\">(</span><span class=\"token number\">0</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>Navbar <span class=\"token operator\">/</span><span class=\"token operator\">></span>\n      <span class=\"token operator\">&lt;</span>Panel counter<span class=\"token operator\">=</span><span class=\"token punctuation\">{</span>counter<span class=\"token punctuation\">}</span> setCounter<span class=\"token operator\">=</span><span class=\"token punctuation\">{</span>setCounter<span class=\"token punctuation\">}</span> <span class=\"token operator\">/</span><span class=\"token operator\">></span>\n      <span class=\"token operator\">&lt;</span>Footer <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>El nuevo componente <i>Panel</i> renderiza los componentes que muestran el contador y los botones:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token keyword\">import</span> Display <span class=\"token keyword\">from</span> <span class=\"token string\">'./Display'</span>\n<span class=\"token keyword\">import</span> Controls <span class=\"token keyword\">from</span> <span class=\"token string\">'./Controls'</span>\n\n<span class=\"token keyword\">const</span> <span class=\"token function-variable function\">Panel</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\"><span class=\"token punctuation\">{</span> counter<span class=\"token punctuation\">,</span> setCounter <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\">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>Display counter<span class=\"token operator\">=</span><span class=\"token punctuation\">{</span>counter<span class=\"token punctuation\">}</span> <span class=\"token operator\">/</span><span class=\"token operator\">></span>\n      <span class=\"token operator\">&lt;</span>Controls counter<span class=\"token operator\">=</span><span class=\"token punctuation\">{</span>counter<span class=\"token punctuation\">}</span> setCounter<span class=\"token operator\">=</span><span class=\"token punctuation\">{</span>setCounter<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></code></pre></div>\n<p>La jerarquía de componentes es la siguiente:</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">App (state)\n ├── Panel \n │    ├── Display\n │    └── Controls\n └── Footer</code></pre></div>\n<p>El estado continúa en <i>App</i>. Para que <i>Display</i> y <i>Controls</i> accedan al contador, tanto el estado como su función de actualización deben atravesar <i>Panel</i> como props, aunque <i>Panel</i> no los necesite. Esta situación aparece fácilmente al utilizar estado creado con <i>useState</i> y se denomina <a href=\"https://kentcdodds.com/blog/prop-drilling\">prop drilling</a>.</p>\n<p>La <a href=\"https://react.dev/learn/passing-data-deeply-with-context\">Context API</a> integrada en React ofrece una solución. Un contexto de React es una especie de estado global de la aplicación al que se puede dar acceso directo a cualquier componente.</p>\n<p>Creemos un contexto que almacene la gestión del estado del contador.</p>\n<p>El contexto se crea con <a href=\"https://react.dev/reference/react/createContext\">createContext</a>. Lo definiremos en el archivo <i>src/CounterContext.jsx</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> createContext <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">'react'</span>\n\n<span class=\"token keyword\">const</span> CounterContext <span class=\"token operator\">=</span> <span class=\"token function\">createContext</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n\n<span class=\"token keyword\">export</span> <span class=\"token keyword\">default</span> CounterContext</code></pre></div>\n<p>El componente <i>App</i> puede <i>proporcionar</i> el contexto a sus componentes hijos así:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token comment\">// ...</span>\n<span class=\"token keyword\">import</span> CounterContext <span class=\"token keyword\">from</span> <span class=\"token string\">'./components/CounterContext'</span>\n\n<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>counter<span class=\"token punctuation\">,</span> setCounter<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token function\">useState</span><span class=\"token punctuation\">(</span><span class=\"token number\">0</span><span class=\"token punctuation\">)</span>\n\n  <span class=\"token keyword\">return</span> <span class=\"token punctuation\">(</span>\n<span class=\"gatsby-highlight-code-line\">    <span class=\"token operator\">&lt;</span>CounterContext<span class=\"token punctuation\">.</span>Provider value<span class=\"token operator\">=</span><span class=\"token punctuation\">{</span><span class=\"token punctuation\">{</span>counter<span class=\"token punctuation\">,</span> setCounter<span class=\"token punctuation\">}</span><span class=\"token punctuation\">}</span><span class=\"token operator\">></span></span><span class=\"gatsby-highlight-code-line\">      <span class=\"token operator\">&lt;</span>Panel <span class=\"token operator\">/</span><span class=\"token operator\">></span></span>      <span class=\"token operator\">&lt;</span>Footer <span class=\"token operator\">/</span><span class=\"token operator\">></span>\n<span class=\"gatsby-highlight-code-line\">    <span class=\"token operator\">&lt;</span><span class=\"token operator\">/</span>CounterContext<span class=\"token punctuation\">.</span>Provider<span class=\"token operator\">></span></span>  <span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>El contexto se proporciona envolviendo los componentes hijos con <i>CounterContext.Provider</i> y asignándole un valor adecuado.</p>\n<p>Su valor es ahora un objeto con los atributos <i>counter</i> y <i>setCounter</i>: el estado del contador y la función que lo actualiza.</p>\n<p>Como <i>Panel</i> ya no recibe props relacionadas con el contador, se simplifica:</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\">Panel</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\">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>Display <span class=\"token operator\">/</span><span class=\"token operator\">></span>\n      <span class=\"token operator\">&lt;</span>Controls <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>Los demás componentes pueden acceder al contexto mediante el hook <a href=\"https://react.dev/reference/react/useContext\">useContext</a>. <i>Display</i> cambia de la siguiente manera:</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\">import</span> <span class=\"token punctuation\">{</span> useContext <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">'react'</span></span><span class=\"gatsby-highlight-code-line\"><span class=\"token keyword\">import</span> CounterContext <span class=\"token keyword\">from</span> <span class=\"token string\">'./CounterContext'</span></span>\n<span class=\"gatsby-highlight-code-line\"><span class=\"token keyword\">const</span> <span class=\"token function-variable function\">Display</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> <span class=\"token punctuation\">{</span> counter <span class=\"token punctuation\">}</span> <span class=\"token operator\">=</span> <span class=\"token function\">useContext</span><span class=\"token punctuation\">(</span>CounterContext<span class=\"token punctuation\">)</span></span>\n  <span class=\"token keyword\">return</span> <span class=\"token operator\">&lt;</span>div<span class=\"token operator\">></span><span class=\"token punctuation\">{</span>counter<span class=\"token punctuation\">}</span><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><i>Display</i> ya no necesita props. Obtiene el contador llamando a <i>useContext</i> con el objeto <i>CounterContext</i> como parámetro.</p>\n<p>De forma análoga, <i>Controls</i> pasa a ser:</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\">import</span> <span class=\"token punctuation\">{</span> useContext <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">'react'</span></span><span class=\"gatsby-highlight-code-line\"><span class=\"token keyword\">import</span> CounterContext <span class=\"token keyword\">from</span> <span class=\"token string\">'./CounterContext'</span></span>\n<span class=\"token keyword\">const</span> <span class=\"token function-variable function\">Controls</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> counter<span class=\"token punctuation\">,</span> setCounter <span class=\"token punctuation\">}</span> <span class=\"token operator\">=</span> <span class=\"token function\">useContext</span><span class=\"token punctuation\">(</span>CounterContext<span class=\"token punctuation\">)</span></span>\n  <span class=\"token keyword\">const</span> <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\">setCounter</span><span class=\"token punctuation\">(</span>counter <span class=\"token operator\">+</span> <span class=\"token number\">1</span><span class=\"token punctuation\">)</span>\n  <span class=\"token keyword\">const</span> <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\">setCounter</span><span class=\"token punctuation\">(</span>counter <span class=\"token operator\">-</span> <span class=\"token number\">1</span><span class=\"token punctuation\">)</span>\n  <span class=\"token keyword\">const</span> <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\">setCounter</span><span class=\"token punctuation\">(</span><span class=\"token number\">0</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>button onClick<span class=\"token operator\">=</span><span class=\"token punctuation\">{</span>increment<span class=\"token punctuation\">}</span><span class=\"token operator\">></span>plus<span class=\"token operator\">&lt;</span><span class=\"token operator\">/</span>button<span class=\"token operator\">></span>\n      <span class=\"token operator\">&lt;</span>button onClick<span class=\"token operator\">=</span><span class=\"token punctuation\">{</span>decrement<span class=\"token punctuation\">}</span><span class=\"token operator\">></span>minus<span class=\"token operator\">&lt;</span><span class=\"token operator\">/</span>button<span class=\"token operator\">></span>\n      <span class=\"token operator\">&lt;</span>button onClick<span class=\"token operator\">=</span><span class=\"token punctuation\">{</span>zero<span class=\"token punctuation\">}</span><span class=\"token operator\">></span>zero<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>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> Controls</code></pre></div>\n<p>Los componentes ya tienen acceso al contenido establecido por el proveedor: el estado del contador y su función de actualización.</p>\n<p>Extraen los atributos que necesitan mediante la desestructuración de JavaScript:</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> counter <span class=\"token punctuation\">}</span> <span class=\"token operator\">=</span> <span class=\"token function\">useContext</span><span class=\"token punctuation\">(</span>CounterContext<span class=\"token punctuation\">)</span></code></pre></div>\n<h3>Definir el contexto del contador en su propio archivo</h3>\n<p>La aplicación aún tiene un aspecto poco agradable: la gestión del estado del contador está definida dentro de <i>App</i>. Traslademos todo el código relacionado al archivo <i>CounterContext.jsx</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> createContext<span class=\"token punctuation\">,</span> useState <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">'react'</span>\n\n<span class=\"token keyword\">const</span> CounterContext <span class=\"token operator\">=</span> <span class=\"token function\">createContext</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n\n<span class=\"token keyword\">export</span> <span class=\"token keyword\">default</span> CounterContext\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\">CounterContextProvider</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">props</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> <span class=\"token punctuation\">[</span>counter<span class=\"token punctuation\">,</span> setCounter<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token function\">useState</span><span class=\"token punctuation\">(</span><span class=\"token number\">0</span><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 punctuation\">(</span></span><span class=\"gatsby-highlight-code-line\">    <span class=\"token operator\">&lt;</span>CounterContext<span class=\"token punctuation\">.</span>Provider value<span class=\"token operator\">=</span><span class=\"token punctuation\">{</span><span class=\"token punctuation\">{</span> counter<span class=\"token punctuation\">,</span> setCounter <span class=\"token punctuation\">}</span><span class=\"token punctuation\">}</span><span class=\"token operator\">></span></span><span class=\"gatsby-highlight-code-line\">      <span class=\"token punctuation\">{</span>props<span class=\"token punctuation\">.</span>children<span class=\"token punctuation\">}</span></span><span class=\"gatsby-highlight-code-line\">    <span class=\"token operator\">&lt;</span><span class=\"token operator\">/</span>CounterContext<span class=\"token punctuation\">.</span>Provider<span class=\"token operator\">></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></code></pre></div>\n<p>El archivo exporta tanto <i>CounterContext</i> como <i>CounterContextProvider</i>, que es esencialmente un proveedor cuyo valor contiene el contador y su función de actualización.</p>\n<p>Utilicemos el proveedor directamente en <i>main.jsx</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> StrictMode <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">'react'</span>\n<span class=\"token keyword\">import</span> <span class=\"token punctuation\">{</span> createRoot <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">'react-dom/client'</span>\n\n<span class=\"token keyword\">import</span> App <span class=\"token keyword\">from</span> <span class=\"token string\">'./App'</span>\n<span class=\"gatsby-highlight-code-line\"><span class=\"token keyword\">import</span> <span class=\"token punctuation\">{</span> CounterContextProvider <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">'./CounterContext'</span></span>\n<span class=\"token function\">createRoot</span><span class=\"token punctuation\">(</span>document<span class=\"token punctuation\">.</span><span class=\"token function\">getElementById</span><span class=\"token punctuation\">(</span><span class=\"token string\">'root'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">render</span><span class=\"token punctuation\">(</span>\n<span class=\"gatsby-highlight-code-line\">  <span class=\"token operator\">&lt;</span>CounterContextProvider<span class=\"token operator\">></span></span>    <span class=\"token operator\">&lt;</span>App <span class=\"token operator\">/</span><span class=\"token operator\">></span>\n<span class=\"gatsby-highlight-code-line\">  <span class=\"token operator\">&lt;</span><span class=\"token operator\">/</span>CounterContextProvider<span class=\"token operator\">></span></span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>El contexto que define el valor y la funcionalidad del contador está ahora disponible para <i>todos</i> los componentes.</p>\n<p><i>App</i> se simplifica:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token keyword\">import</span> Panel <span class=\"token keyword\">from</span> <span class=\"token string\">'./components/Panel'</span>\n<span class=\"token keyword\">import</span> Footer <span class=\"token keyword\">from</span> <span class=\"token string\">'./components/Footer'</span>\n\n<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\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>Navbar <span class=\"token operator\">/</span><span class=\"token operator\">></span>\n      <span class=\"token operator\">&lt;</span>Panel <span class=\"token operator\">/</span><span class=\"token operator\">></span>\n      <span class=\"token operator\">&lt;</span>Footer <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> App</code></pre></div>\n<p>El contexto sigue utilizándose igual y los demás componentes no necesitan cambios. Por ejemplo, <i>Controls</i> permanece así:</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\">Controls</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> counter<span class=\"token punctuation\">,</span> setCounter <span class=\"token punctuation\">}</span> <span class=\"token operator\">=</span> <span class=\"token function\">useContext</span><span class=\"token punctuation\">(</span>CounterContext<span class=\"token punctuation\">)</span>\n  <span class=\"token keyword\">const</span> <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\">setCounter</span><span class=\"token punctuation\">(</span>counter <span class=\"token operator\">+</span> <span class=\"token number\">1</span><span class=\"token punctuation\">)</span>\n  <span class=\"token keyword\">const</span> <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\">setCounter</span><span class=\"token punctuation\">(</span>counter <span class=\"token operator\">-</span> <span class=\"token number\">1</span><span class=\"token punctuation\">)</span>\n  <span class=\"token keyword\">const</span> <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\">setCounter</span><span class=\"token punctuation\">(</span><span class=\"token number\">0</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>button onClick<span class=\"token operator\">=</span><span class=\"token punctuation\">{</span>increment<span class=\"token punctuation\">}</span><span class=\"token operator\">></span>plus<span class=\"token operator\">&lt;</span><span class=\"token operator\">/</span>button<span class=\"token operator\">></span>\n      <span class=\"token operator\">&lt;</span>button onClick<span class=\"token operator\">=</span><span class=\"token punctuation\">{</span>decrement<span class=\"token punctuation\">}</span><span class=\"token operator\">></span>minus<span class=\"token operator\">&lt;</span><span class=\"token operator\">/</span>button<span class=\"token operator\">></span>\n      <span class=\"token operator\">&lt;</span>button onClick<span class=\"token operator\">=</span><span class=\"token punctuation\">{</span>zero<span class=\"token punctuation\">}</span><span class=\"token operator\">></span>zero<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>div<span class=\"token operator\">></span>\n  <span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>La solución es bastante buena. Todo el estado de la aplicación —el valor del contador— queda aislado en <i>CounterContext</i>. Cada componente accede exactamente a la parte que necesita mediante <i>useContext</i> y la desestructuración.</p>\n<p>Hagamos una pequeña mejora y definamos también las funciones <i>increment</i>, <i>decrement</i> y <i>zero</i> dentro del contexto:</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> createContext<span class=\"token punctuation\">,</span> useState <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">'react'</span>\n\n<span class=\"token keyword\">const</span> CounterContext <span class=\"token operator\">=</span> <span class=\"token function\">createContext</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n\n<span class=\"token keyword\">export</span> <span class=\"token keyword\">default</span> CounterContext\n\n<span class=\"token keyword\">export</span> <span class=\"token keyword\">const</span> <span class=\"token function-variable function\">CounterContextProvider</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">props</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>counter<span class=\"token punctuation\">,</span> setCounter<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token function\">useState</span><span class=\"token punctuation\">(</span><span class=\"token number\">0</span><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\">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\">setCounter</span><span class=\"token punctuation\">(</span>counter <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 keyword\">const</span> <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\">setCounter</span><span class=\"token punctuation\">(</span>counter <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 keyword\">const</span> <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\">setCounter</span><span class=\"token punctuation\">(</span><span class=\"token number\">0</span><span class=\"token punctuation\">)</span></span>\n  <span class=\"token keyword\">return</span> <span class=\"token punctuation\">(</span>\n<span class=\"gatsby-highlight-code-line\">    <span class=\"token operator\">&lt;</span>CounterContext<span class=\"token punctuation\">.</span>Provider value<span class=\"token operator\">=</span><span class=\"token punctuation\">{</span><span class=\"token punctuation\">{</span> counter<span class=\"token punctuation\">,</span> increment<span class=\"token punctuation\">,</span> decrement<span class=\"token punctuation\">,</span> zero <span class=\"token punctuation\">}</span><span class=\"token punctuation\">}</span><span class=\"token operator\">></span></span>      <span class=\"token punctuation\">{</span>props<span class=\"token punctuation\">.</span>children<span class=\"token punctuation\">}</span>\n    <span class=\"token operator\">&lt;</span><span class=\"token operator\">/</span>CounterContext<span class=\"token punctuation\">.</span>Provider<span class=\"token operator\">></span>\n  <span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>Ahora podemos usar las funciones obtenidas del contexto directamente como controladores de eventos:</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> useContext <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">'react'</span>\n<span class=\"token keyword\">import</span> CounterContext <span class=\"token keyword\">from</span> <span class=\"token string\">'../CounterContext'</span> \n\n<span class=\"token keyword\">const</span> <span class=\"token function-variable function\">Controls</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> increment<span class=\"token punctuation\">,</span> decrement<span class=\"token punctuation\">,</span> zero <span class=\"token punctuation\">}</span> <span class=\"token operator\">=</span> <span class=\"token function\">useContext</span><span class=\"token punctuation\">(</span>CounterContext<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>button onClick<span class=\"token operator\">=</span><span class=\"token punctuation\">{</span>increment<span class=\"token punctuation\">}</span><span class=\"token operator\">></span>plus<span class=\"token operator\">&lt;</span><span class=\"token operator\">/</span>button<span class=\"token operator\">></span>\n      <span class=\"token operator\">&lt;</span>button onClick<span class=\"token operator\">=</span><span class=\"token punctuation\">{</span>decrement<span class=\"token punctuation\">}</span><span class=\"token operator\">></span>minus<span class=\"token operator\">&lt;</span><span class=\"token operator\">/</span>button<span class=\"token operator\">></span>\n      <span class=\"token operator\">&lt;</span>button onClick<span class=\"token operator\">=</span><span class=\"token punctuation\">{</span>zero<span class=\"token punctuation\">}</span><span class=\"token operator\">></span>zero<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>div<span class=\"token operator\">></span>\n  <span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>Todavía podemos mejorarlo. Al observar el uso del contexto, vemos el mismo código repetitivo en ambos componentes que lo consumen:</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> useContext <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">'react'</span>\n<span class=\"token keyword\">import</span> CounterContext <span class=\"token keyword\">from</span> <span class=\"token string\">'../CounterContext'</span> \n\n<span class=\"token keyword\">const</span> <span class=\"token function-variable function\">Display</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> counter <span class=\"token punctuation\">}</span> <span class=\"token operator\">=</span> <span class=\"token function\">useContext</span><span class=\"token punctuation\">(</span>CounterContext<span class=\"token punctuation\">)</span>\n  <span class=\"token comment\">// ...</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\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> useContext <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">'react'</span>\n<span class=\"token keyword\">import</span> CounterContext <span class=\"token keyword\">from</span> <span class=\"token string\">'../CounterContext'</span> \n\n<span class=\"token keyword\">const</span> <span class=\"token function-variable function\">Controls</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> increment<span class=\"token punctuation\">,</span> decrement<span class=\"token punctuation\">,</span> zero <span class=\"token punctuation\">}</span> <span class=\"token operator\">=</span> <span class=\"token function\">useContext</span><span class=\"token punctuation\">(</span>CounterContext<span class=\"token punctuation\">)</span></span>  <span class=\"token comment\">// ...</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>Podemos avanzar un paso más creando un hook personalizado que devuelva directamente el contexto. Añadámoslo al archivo <i>hooks/useCounter.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> useContext <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">'react'</span>\n<span class=\"token keyword\">import</span> CounterContext <span class=\"token keyword\">from</span> <span class=\"token string\">'../CounterContext'</span>\n\n<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\">useContext</span><span class=\"token punctuation\">(</span>CounterContext<span class=\"token punctuation\">)</span>\n\n<span class=\"token keyword\">export</span> <span class=\"token keyword\">default</span> useCounter</code></pre></div>\n<p>El uso del contexto queda aún más sencillo:</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> useCounter <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">'../hooks/useCounter'</span>\n\n<span class=\"token keyword\">const</span> <span class=\"token function-variable function\">Display</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> counter <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>\n  <span class=\"token comment\">// ...</span>\n<span class=\"token punctuation\">}</span>\n\n<span class=\"token keyword\">import</span> <span class=\"token punctuation\">{</span> useCounter <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">'../hooks/useCounter'</span>\n\n<span class=\"token keyword\">const</span> <span class=\"token function-variable function\">Controls</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> increment<span class=\"token punctuation\">,</span> decrement<span class=\"token punctuation\">,</span> zero <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>\n  <span class=\"token comment\">// ...</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>La solución nos satisface. Aísla toda la gestión del estado dentro del contexto. Los componentes que lo usan desconocen cómo se implementa; gracias al hook personalizado, ni siquiera necesitan saber que la solución se basa en la Context API.</p>\n<p>El código de la aplicación está en el repositorio de GitHub <a href=\"https://github.com/fullstack-hy2020/context-counter\">https://github.com/fullstack-hy2020/context-counter</a>.</p>\n</div>\n<div class=\"tasks\">\n<h3>Ejercicios 6.20.-6.22.</h3>\n<h4>Ejercicio 6.20.</h4>\n<p>La aplicación tiene un componente <i>Notification</i> para mostrar notificaciones al usuario.</p>\n<p>Implementa la gestión del estado de las notificaciones de la aplicación utilizando la Context API. La notificación debe informar al usuario cuando se crea una nueva anécdota o cuando se vota por ella:</p>\n<picture><img src=\"/static/624eb96335944fbc330519085b862c61/5a190/66new.png\" alt=\"navegador mostrando notificación para anécdota añadida\" srcset=\"/static/624eb96335944fbc330519085b862c61/772e8/66new.png 200w,\n/static/624eb96335944fbc330519085b862c61/e17e5/66new.png 400w,\n/static/624eb96335944fbc330519085b862c61/5a190/66new.png 800w,\n/static/624eb96335944fbc330519085b862c61/c1b63/66new.png 1200w,\n/static/624eb96335944fbc330519085b862c61/0d390/66new.png 1472w\" sizes=\"(max-width: 800px) 100vw, 800px\"></picture>\n<p>La notificación se muestra durante cinco segundos.</p>\n<h4>Ejercicio 6.21.</h4>\n<p>Como se indicó en el ejercicio 6.17, el servidor exige que el contenido de la anécdota que se añade tenga al menos 5 caracteres. Implementa ahora el manejo de errores de la inserción. En la práctica basta con mostrar una notificación cuando falle la solicitud POST:</p>\n<picture><img src=\"/static/6421e83d12bd88962ba24fde52f3a719/5a190/67new.png\" alt=\"navegador mostrando notificación de error por tratar de crear una anécdota muy corta\" srcset=\"/static/6421e83d12bd88962ba24fde52f3a719/772e8/67new.png 200w,\n/static/6421e83d12bd88962ba24fde52f3a719/e17e5/67new.png 400w,\n/static/6421e83d12bd88962ba24fde52f3a719/5a190/67new.png 800w,\n/static/6421e83d12bd88962ba24fde52f3a719/c1b63/67new.png 1200w,\n/static/6421e83d12bd88962ba24fde52f3a719/29007/67new.png 1600w,\n/static/6421e83d12bd88962ba24fde52f3a719/cea38/67new.png 1644w\" sizes=\"(max-width: 800px) 100vw, 800px\"></picture>\n<p>La condición de error debe manejarse en la función de callback registrada para ello, consulta <a href=\"https://tanstack.com/query/latest/docs/react/reference/useMutation\">aquí</a> cómo registrar una función.</p>\n<h4>Ejercicio 6.22.</h4>\n<p>Si aún no lo has hecho, mueve el contexto de las notificaciones a su propio archivo <i>NotificationContext.jsx</i>, del mismo modo que el contexto de la aplicación del contador se trasladó a <i>CounterContext.jsx</i>. Crea también un hook personalizado <i>useNotify</i> que encapsule la lógica de las notificaciones. Simplifica los componentes que las utilizan para que llamen directamente al hook en lugar de llamar a <i>useContext</i> por separado.</p>\n<p>Este fue el último ejercicio para esta parte del curso y es hora de enviar tu código a GitHub y marcar todos tus ejercicios completados en el <a href=\"https://studies.cs.helsinki.fi/stats/courses/fullstackopen\">sistema de envío de ejercicios</a>.</p>\n</div>\n<div class=\"content\">\n<h3>¿Qué solución de gestión de estado elegir?</h3>\n<p>En los capítulos 1-5, toda la gestión de estado de la aplicación se realizó utilizando el hook de React <i>useState</i>. Las llamadas asíncronas al backend requerían el uso del hook <i>useEffect</i> en algunas situaciones. En principio, no se necesita nada más.</p>\n<p>Un problema sutil con una solución basada en un estado creado con el hook <i>useState</i> es que si alguna parte del estado de la aplicación se necesita en varios componentes de la aplicación, el estado y las funciones para manipularlo deben pasarse via props a todos los componentes que manejan el estado. A veces, las props deben pasar por varios componentes, y los componentes a lo largo del camino pueden ni siquiera estar interesados en el estado de ninguna manera. Este fenómeno algo desagradable se llama <i>prop drilling</i>.</p>\n<p>A lo largo de los años, se han desarrollado varias soluciones alternativas para la gestión de estado de aplicaciones React, que se pueden usar para aliviar situaciones problemáticas (por ejemplo, prop drilling). Sin embargo, ninguna solución ha sido \"final\", todas tienen sus propias ventajas y desventajas, y se están desarrollando nuevas soluciones todo el tiempo.</p>\n<p>La situación puede confundir a un principiante e incluso a un desarrollador web experimentado. ¿Qué solución se debe usar?</p>\n<p>Para una aplicación simple, <i>useState</i> es sin duda un buen punto de partida. Si la aplicación está comunicándose con el servidor, la comunicación se puede manejar de la misma manera que en los capítulos 1-5, utilizando el estado de la aplicación misma. Sin embargo, recientemente se ha vuelto más común mover la comunicación y la gestión asociada del estado al menos parcialmente bajo el control de TanStack Query (o alguna otra librería similar). Si estás preocupado por useState y el prop drilling que conlleva, usar context puede ser una buena opción. También hay situaciones donde puede tener sentido manejar parte del estado con useState y parte con contextos.</p>\n<p>Durante mucho tiempo, la solución más popular y completa fue Redux, una forma de implementar la arquitectura <a href=\"https://facebookarchive.github.io/flux/\">Flux</a>. Sin embargo, Redux es conocido por su complejidad y la abundancia de código repetitivo, lo que motivó la aparición de alternativas más recientes. En este curso Redux se ha sustituido por <a href=\"https://zustand.docs.pmnd.rs/\">Zustand</a>, que ofrece una funcionalidad equivalente con una API mucho más sencilla. Zustand se ha convertido en una opción popular cuando hace falta algo más que useState, pero toda la maquinaria de Redux resulta excesiva. Parte de las críticas a la rigidez de Redux han quedado obsoletas gracias a <a href=\"https://redux-toolkit.js.org/\">Redux Toolkit</a>, y Redux todavía se usa mucho, especialmente en proyectos grandes.</p>\n<p>Ni Zustand ni Redux tienen que utilizarse en toda la aplicación. Por ejemplo, puede ser razonable gestionar fuera de ellos el estado de los formularios cuando no afecta al resto de la aplicación. También es perfectamente posible combinar Zustand o Redux con TanStack Query.</p>\n<p>La pregunta de qué solución de gestión de estado se debe usar no es para nada sencilla. Es imposible dar una sola respuesta correcta. También es probable que la solución de gestión de estado seleccionada pueda resultar ser subóptima a medida que la aplicación crece hasta tal punto que la solución tenga que cambiarse incluso si la aplicación ya ha sido puesta en uso de producción.</p>\n</div>","frontmatter":{"mainImage":{"publicURL":"/static/a3b7bc3fafcb5b47227616e1343970e5/part-6.svg"},"part":6,"letter":"c","lang":"es"}}},"pageContext":{"part":6,"letter":"c","lang":"es"}},"staticQueryHashes":["3128451518"]}