{"slug":"reactivity","title":"Reactivity","headings":["Signal","effect","derived / memo","batch / untrack","Live example"],"contentHtml":"<h1 id=\"reactivity\">Reactivity</h1><h2 id=\"signal\">Signal</h2><pre class=\"shiki github-dark\" style=\"background-color:#17171d;color:#e1e4e8\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#F97583\">import</span><span style=\"color:#E1E4E8\"> { Signal, effect } </span><span style=\"color:#F97583\">from</span><span style=\"color:#9ECBFF\"> \"ruri\"</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#F97583\">const</span><span style=\"color:#79B8FF\"> count</span><span style=\"color:#F97583\"> =</span><span style=\"color:#F97583\"> new</span><span style=\"color:#B392F0\"> Signal</span><span style=\"color:#E1E4E8\">(</span><span style=\"color:#79B8FF\">0</span><span style=\"color:#E1E4E8\">)</span></span>\n<span class=\"line\"><span style=\"color:#E1E4E8\">count.value </span><span style=\"color:#6A737D\">// read (tracks dependencies inside effects)</span></span>\n<span class=\"line\"><span style=\"color:#E1E4E8\">count.</span><span style=\"color:#B392F0\">peek</span><span style=\"color:#E1E4E8\">() </span><span style=\"color:#6A737D\">// read without tracking</span></span>\n<span class=\"line\"><span style=\"color:#E1E4E8\">count.value </span><span style=\"color:#F97583\">=</span><span style=\"color:#79B8FF\"> 1</span><span style=\"color:#6A737D\"> // write (notifies subscribers)</span></span></code></pre><h2 id=\"effect\">effect</h2><pre class=\"shiki github-dark\" style=\"background-color:#17171d;color:#e1e4e8\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#F97583\">const</span><span style=\"color:#79B8FF\"> dispose</span><span style=\"color:#F97583\"> =</span><span style=\"color:#B392F0\"> effect</span><span style=\"color:#E1E4E8\">(() </span><span style=\"color:#F97583\">=></span><span style=\"color:#E1E4E8\"> {</span></span>\n<span class=\"line\"><span style=\"color:#E1E4E8\">  console.</span><span style=\"color:#B392F0\">log</span><span style=\"color:#E1E4E8\">(count.value)</span></span>\n<span class=\"line\"><span style=\"color:#E1E4E8\">})</span></span>\n<span class=\"line\"><span style=\"color:#E1E4E8\">count.value </span><span style=\"color:#F97583\">=</span><span style=\"color:#79B8FF\"> 2</span><span style=\"color:#6A737D\"> // logs 2</span></span>\n<span class=\"line\"><span style=\"color:#B392F0\">dispose</span><span style=\"color:#E1E4E8\">()</span></span></code></pre><p>Dependencies are re-tracked on every run, so conditional reads never leak subscriptions. Cleanups registered with <code>onCleanup</code> run before each re-execution and on dispose.</p><h2 id=\"derived-memo\">derived / memo</h2><pre class=\"shiki github-dark\" style=\"background-color:#17171d;color:#e1e4e8\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#F97583\">const</span><span style=\"color:#79B8FF\"> doubled</span><span style=\"color:#F97583\"> =</span><span style=\"color:#B392F0\"> derived</span><span style=\"color:#E1E4E8\">(() </span><span style=\"color:#F97583\">=></span><span style=\"color:#E1E4E8\"> count.value </span><span style=\"color:#F97583\">*</span><span style=\"color:#79B8FF\"> 2</span><span style=\"color:#E1E4E8\">)</span></span></code></pre><p>Derived signals are memoized and can be disposed to stop the internal computation.</p><h2 id=\"batch-untrack\">batch / untrack</h2><pre class=\"shiki github-dark\" style=\"background-color:#17171d;color:#e1e4e8\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#B392F0\">batch</span><span style=\"color:#E1E4E8\">(() </span><span style=\"color:#F97583\">=></span><span style=\"color:#E1E4E8\"> {</span></span>\n<span class=\"line\"><span style=\"color:#E1E4E8\">  first.value </span><span style=\"color:#F97583\">=</span><span style=\"color:#79B8FF\"> 1</span></span>\n<span class=\"line\"><span style=\"color:#E1E4E8\">  second.value </span><span style=\"color:#F97583\">=</span><span style=\"color:#79B8FF\"> 2</span><span style=\"color:#6A737D\"> // single notification round</span></span>\n<span class=\"line\"><span style=\"color:#E1E4E8\">})</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#B392F0\">untrack</span><span style=\"color:#E1E4E8\">(() </span><span style=\"color:#F97583\">=></span><span style=\"color:#E1E4E8\"> someSignal.value) </span><span style=\"color:#6A737D\">// read without creating a dependency</span></span></code></pre><h2 id=\"live-example\">Live example</h2><div class=\"playground\"><pre class=\"pg-code shiki github-dark\" style=\"background-color:#17171d;color:#e1e4e8\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#F97583\">import</span><span style=\"color:#E1E4E8\"> { derived, effect, Signal, tags } </span><span style=\"color:#F97583\">from</span><span style=\"color:#9ECBFF\"> \"ruri\"</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#F97583\">const</span><span style=\"color:#E1E4E8\"> { </span><span style=\"color:#79B8FF\">div</span><span style=\"color:#E1E4E8\">, </span><span style=\"color:#79B8FF\">input</span><span style=\"color:#E1E4E8\">, </span><span style=\"color:#79B8FF\">strong</span><span style=\"color:#E1E4E8\"> } </span><span style=\"color:#F97583\">=</span><span style=\"color:#E1E4E8\"> tags</span></span>\n<span class=\"line\"><span style=\"color:#F97583\">const</span><span style=\"color:#79B8FF\"> name</span><span style=\"color:#F97583\"> =</span><span style=\"color:#F97583\"> new</span><span style=\"color:#B392F0\"> Signal</span><span style=\"color:#E1E4E8\">(</span><span style=\"color:#9ECBFF\">\"world\"</span><span style=\"color:#E1E4E8\">)</span></span>\n<span class=\"line\"><span style=\"color:#F97583\">const</span><span style=\"color:#79B8FF\"> shout</span><span style=\"color:#F97583\"> =</span><span style=\"color:#B392F0\"> derived</span><span style=\"color:#E1E4E8\">(() </span><span style=\"color:#F97583\">=></span><span style=\"color:#E1E4E8\"> name.value.</span><span style=\"color:#B392F0\">toUpperCase</span><span style=\"color:#E1E4E8\">())</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#F97583\">const</span><span style=\"color:#79B8FF\"> input_</span><span style=\"color:#F97583\"> =</span><span style=\"color:#B392F0\"> input</span><span style=\"color:#E1E4E8\">({ value: name.</span><span style=\"color:#B392F0\">peek</span><span style=\"color:#E1E4E8\">(), </span><span style=\"color:#B392F0\">oninput</span><span style=\"color:#E1E4E8\">: (</span><span style=\"color:#FFAB70\">event</span><span style=\"color:#E1E4E8\">) </span><span style=\"color:#F97583\">=></span><span style=\"color:#E1E4E8\"> { name.value </span><span style=\"color:#F97583\">=</span><span style=\"color:#E1E4E8\"> event.target.value } })</span></span>\n<span class=\"line\"><span style=\"color:#E1E4E8\">output.</span><span style=\"color:#B392F0\">append</span><span style=\"color:#E1E4E8\">(</span><span style=\"color:#B392F0\">div</span><span style=\"color:#E1E4E8\">({}, </span><span style=\"color:#9ECBFF\">\"hello, \"</span><span style=\"color:#E1E4E8\">, input_, </span><span style=\"color:#9ECBFF\">\"! \"</span><span style=\"color:#E1E4E8\">, </span><span style=\"color:#B392F0\">strong</span><span style=\"color:#E1E4E8\">({}, shout)))</span></span></code></pre><div class=\"pg-view\" id=\"pg-view-1\"><span class=\"pg-hint\">running...</span></div></div>"}