{"id":10758,"date":"2024-03-30T15:18:28","date_gmt":"2024-03-30T15:18:28","guid":{"rendered":"https:\/\/putridparrot.com\/blog\/?p=10758"},"modified":"2024-03-30T15:20:14","modified_gmt":"2024-03-30T15:20:14","slug":"react-with-signals","status":"publish","type":"post","link":"https:\/\/putridparrot.com\/blog\/react-with-signals\/","title":{"rendered":"React with Signals"},"content":{"rendered":"<p>Signals are another way of managing application state. <\/p>\n<p>You might ask, &#8220;well great but we already have hooks like <em>useState<\/em> so what&#8217;s the point?&#8221;<\/p>\n<p>In answer to the above perfectly valid question, Signals work on a in a more granular way &#8211; let&#8217;s compare to <em>useState<\/em>. If we create a simple little (and pretty standard) counter component we can immediately see the differences.<\/p>\n<p>Create yourself a React application, I&#8217;m using yarn but use your preferred package manager.<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nyarn create react-app react-with-signals --template typescript\r\n<\/pre>\n<p>Add the signal package using<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nyarn add @preact\/signals-react\r\n<\/pre>\n<p>Now we&#8217;ll create a folder named <em>components<\/em> and add a file named <em>CounterState.tsx<\/em> which looks like this<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\nimport { useState } from &quot;react&quot;;\r\n\r\nexport const CounterState = () =&gt; {\r\n  const &#x5B;count, setCount] = useState(0);\r\n\r\n  console.log(&quot;Render CounterState&quot;);\r\n\r\n  return (\r\n    &lt;div&gt;\r\n      &lt;div&gt;Current Value {count}&lt;\/div&gt;\r\n      &lt;div&gt;\r\n        &lt;button onClick={() =&gt; setCount(count - 1)}&gt;Decrement&lt;\/button&gt;\r\n        &lt;button onClick={() =&gt; setCount(count + 1)}&gt;Increment&lt;\/button&gt;\r\n      &lt;\/div&gt;\r\n    &lt;\/div&gt;\r\n  );\r\n}\r\n<\/pre>\n<p>It&#8217;s not very pretty but it&#8217;s good enough for this demonstration. <\/p>\n<p>Finally create a new file in the <em>components<\/em> folder named CounterSignals.tsx which should look like this<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\nimport React from &#039;react&#039;;\r\nimport { useSignal } from &quot;@preact\/signals-react&quot;;\r\n\r\nexport const CounterSignals = () =&gt; {\r\n  const count = useSignal(0);\r\n\r\n  console.log(&quot;Render CounterSignals&quot;);\r\n\r\n  return (\r\n    &lt;div&gt;\r\n      &lt;div&gt;Current Value {count}&lt;\/div&gt;\r\n      &lt;div&gt;\r\n        &lt;button onClick={() =&gt; count.value--}&gt;Decrement&lt;\/button&gt;\r\n        &lt;button onClick={() =&gt; count.value++}&gt;Increment&lt;\/button&gt;\r\n      &lt;\/div&gt;\r\n    &lt;\/div&gt;\r\n  );\r\n}\r\n<\/pre>\n<p>As you can see, the Signals code creates a Signals object instead of the destructuring way used with <em>useState<\/em> and the Signals object will not change, but when we change the <em>value<\/em>, the value within the object changes but does not re-rendering the entire component each time.<\/p>\n<p>Let&#8217;s see this by watching the console output in our preferred browser, so just change <em>App.tsx<\/em> to look like this<\/p>\n<p>import React from &#8216;react&#8217;;<br \/>\nimport { CounterState } from &#8216;.\/components\/CounterState&#8217;;<br \/>\nimport { CounterSignals } from &#8216;.\/components\/CounterSignals&#8217;;<\/p>\n<p>function App() {<br \/>\n  return (<\/p>\n<div className=\"App\">\n      <CounterState \/><br \/>\n      <CounterSignals \/>\n    <\/div>\n<p>  );<br \/>\n}<\/p>\n<p>export default App;<br \/>\n[\/em]<\/p>\n<p>Start the application. You might wish to disable <em>React.StrictMode<\/em> in the <em>index.tsx<\/em> as this will double up the console output whilst in DEV mode.<\/p>\n<p>Click the Increment and Decrement buttons and you&#8217;ll see our <em>useState<\/em> implementation renders on each click whereas the counter changes for the Signals version but no re-rendering happens.<\/p>\n<p><strong>Code<\/strong><\/p>\n<p>Code for this example using Signals can be found on <a href=\"https:\/\/github.com\/putridparrot\/blog-projects\/tree\/master\/ReactWithSignals\/react-with-signals\" rel=\"noopener\" target=\"_blank\">github<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Signals are another way of managing application state. You might ask, &#8220;well great but we already have hooks like useState so what&#8217;s the point?&#8221; In answer to the above perfectly valid question, Signals work on a in a more granular way &#8211; let&#8217;s compare to useState. If we create a simple little (and pretty standard) [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[243,723],"tags":[],"class_list":["post-10758","post","type-post","status-publish","format-standard","hentry","category-react","category-signals"],"jetpack_sharing_enabled":true,"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts\/10758","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/comments?post=10758"}],"version-history":[{"count":3,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts\/10758\/revisions"}],"predecessor-version":[{"id":10768,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts\/10758\/revisions\/10768"}],"wp:attachment":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/media?parent=10758"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/categories?post=10758"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/tags?post=10758"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}