<turbo-stream action="append" target="posts_list"><template>    <div class="postbit" id="377069" data-post-id="377069">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="garrison" src="/assets/icons/user-9f439610.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  garrison
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="bartblast" data-post="28" data-topic="73073">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/bartblast/48/17647_2.png" class="avatar"> bartblast:</div>
<blockquote>
<p>That’s a bit of rhetorical judo there</p>
</blockquote>
</aside>
<p>lol I am not trying to trick you into agreeing with me. I think the fact that there is <a href="https://github.com/reactjs/react-basic" rel="noopener nofollow ugc">considerable historical evidence</a> that the React devs were <em>explicitly</em> trying to emulate functional paradigms is very important context. Their intent was <em>not</em> to expose an abstraction of global mutable state. The fact that it’s hiding underneath is an implementation detail in the same way that the BEAM being written in (mutable) C is an implementation detail.</p>
<p>Anyway, algebraic effects are not actually needed to implement Hooks either, it’s just a more ergonomic way to handle the control flow. Similarly, it’s more ergonomic for an Ecto transaction to be implicit rather than passing around a <code>%Transaction{}</code> struct for every <code>Repo</code> call. I have actually <em>done</em> the latter, by the way, and it sucks.</p>
<p>Algebraic effects are a way to “legitimize” that sort of API <em>instead</em> of abusing global state. Whether you like them or not is up to you, but again I think it’s important to understand the <em>intent</em> of the React team at the time. They <em>wanted</em> a functional API.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="377069" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/composability-patterns-for-hologram-looking-for-your-ideas/73073/32">Post #31</a>
	                </div>
	            </div>
              <div id="likers-container-377069" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="377069"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #31"></div>
  </section>
</div>
    <div class="postbit" id="377074" data-post-id="377074">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="garrison" src="/assets/icons/user-9f439610.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  garrison
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Hooks are actually very simple. Here’s a pure functional hook:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">def use_state(hooks, default_value \\ nil) do
  pointer = hooks.pointer
  # Closes over the pointer
  setter = fn hooks, update_fun -&gt;
    %{hooks | array: Map.update(hooks.array, pointer, update_fun)}
  end
  value = Map.get(hooks.array, pointer, default_value)

  hooks = %{hooks |
    Map.put(hooks.array, pointer, value),
    pointer: pointer + 1,
  }
  {hooks, {value, setter}}
end
</code></pre>
<p>And it composes!</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">def use_toggle(hooks) do
  {hooks, {enabled, set_enabled}} = use_state(hooks, false)
  toggle = fn hooks -&gt;
    set_enabled.(hooks, &amp;(not &amp;1))
  end
  {hooks, {enabled, toggle}}
end
</code></pre>
<p>In a “component”, setting the value in the component body because I cannot be bothered to make up an event system:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">def component(hooks) do
  {hooks, {enabled, toggle}} = use_toggle(hooks)
  hooks = toggle.(hooks)
  {"&lt;div&gt;#{to_string(enabled)}&lt;/div&gt;", hooks}
end

hooks = %{array: %{}, pointer: 0}
{"&lt;div&gt;false&lt;/div&gt;", hooks} = component(hooks)
# Re-render:
hooks = %{hooks | pointer: 0}
{"&lt;div&gt;true&lt;/div&gt;", hooks} = component(hooks)
</code></pre>
<p>Obviously I am too lazy to test this so there might be mistakes, but hopefully you get the point.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="377074" data-batch-url="/posts/batch_likers">
                        2
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/composability-patterns-for-hologram-looking-for-your-ideas/73073/33">Post #32</a>
	                </div>
	            </div>
              <div id="likers-container-377074" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="377074"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #32"></div>
  </section>
</div>
    <div class="postbit" id="377110" data-post-id="377110">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="bartblast" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/bartblast/120/17647_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  bartblast
                    <span class="op-star" title="Thread Starter">
                      <img alt="OP" class="op-star-icon" src="/assets/thread-icons/thread-icon-thread-starter-df91e872.png" />
                    </span>
                  </h3>
		          </div>
						
			          <div class="user-title">
									<span>Creator of Hologram</span>
			          </div>
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="nikfp" data-post="29" data-topic="73073">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/nikfp/48/37207_2.png" class="avatar"> nikfp:</div>
<blockquote>
<p>For mixins as you described, I can see the dx being comfortable in simple cases, but I can also see that turning into a headache as things gain any complexity. Thinking about testing and debugging for example, you would have to grok the component <em>and everything that has been injected into it</em> to work on or diagnose anything.</p>
</blockquote>
</aside>
<p>That’s definitely a valid concern with mixins. Though macros could inject introspection utilities to help with that. Just one of the options to consider.</p>
<aside class="quote no-group" data-username="nikfp" data-post="29" data-topic="73073">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/nikfp/48/37207_2.png" class="avatar"> nikfp:</div>
<blockquote>
<p>Namespacing could be interesting. I was thinking in my example that the keys would relate to the root component and the store together, and the machinery behind isolating all of that would be largely abstracted. The usage would be explicit though. It sounds like you are thinking that the namespacing would be more explicit and the plumbing would be abstracted and hooked up during compile time. Which is fine, and that’s what some JS frameworks already do, so I don’t think the mental overhead would be hard to grasp for users.</p>
</blockquote>
</aside>
<p>I’m considering two main approaches (with different variants) for namespacing:</p>
<ol>
<li>using the module as a namespace key, like <code>def action({Togglable, :do_sth}, ...)</code> where action names, state, etc. get namespaced automatically.</li>
<li>explicit prefixed keys like <code>def action(:togglable_do_sth, ...)</code>.</li>
</ol>
<p>Still an open question how to integrate this cleanly and whether full automation is feasible.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="377110" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/composability-patterns-for-hologram-looking-for-your-ideas/73073/34">Post #33</a>
	                </div>
	            </div>
              <div id="likers-container-377110" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="377110"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #33"></div>
  </section>
</div>
    <div class="postbit" id="377114" data-post-id="377114">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="nikfp" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/nikfp/120/37207_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  nikfp
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="bartblast" data-post="34" data-topic="73073">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/bartblast/48/17647_2.png" class="avatar"> bartblast:</div>
<blockquote>
<ul>
<li>using the module as a namespace key, like <code>def action({Togglable, :do_sth}, ...)</code> where action names, state, etc. get namespaced automatically.</li>
<li>explicit prefixed keys like <code>def action(:togglable_do_sth, ...)</code>.</li>
</ul>
</blockquote>
</aside>
<p>Do you have an idea in mind for uniquely identifying each instance? Or at the least, preventing naming collisions through a compile time check?</p>
<p>There may also be value in having the keys dynamically generated, which would then require some kind of unique id that I would expect would relate back to the root component. Im thinking of an example where you have N list entries, and each one is represented by a component tree with a store at the top.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="377114" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/composability-patterns-for-hologram-looking-for-your-ideas/73073/35">Post #34</a>
	                </div>
	            </div>
              <div id="likers-container-377114" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="377114"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #34"></div>
  </section>
</div>
    <div class="postbit" id="377115" data-post-id="377115">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="bartblast" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/bartblast/120/17647_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  bartblast
                    <span class="op-star" title="Thread Starter">
                      <img alt="OP" class="op-star-icon" src="/assets/thread-icons/thread-icon-thread-starter-df91e872.png" />
                    </span>
                  </h3>
		          </div>
						
			          <div class="user-title">
									<span>Creator of Hologram</span>
			          </div>
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="garrison" data-post="33" data-topic="73073" data-full="true">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/letter_avatar_proxy/v4/letter/g/3bc359/48.png" class="avatar"> garrison:</div>
<blockquote>
<p>Hooks are actually very simple. Here’s a pure functional hook:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">def use_state(hooks, default_value \\ nil) do
  pointer = hooks.pointer
  # Closes over the pointer
  setter = fn hooks, update_fun -&gt;
    %{hooks | array: Map.update(hooks.array, pointer, update_fun)}
  end
  value = Map.get(hooks.array, pointer, default_value)

  hooks = %{hooks |
    Map.put(hooks.array, pointer, value),
    pointer: pointer + 1,
  }
  {hooks, {value, setter}}
end
</code></pre>
<p>And it composes!</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">def use_toggle(hooks) do
  {hooks, {enabled, set_enabled}} = use_state(hooks, false)
  toggle = fn hooks -&gt;
    set_enabled.(hooks, &amp;(not &amp;1))
  end
  {hooks, {enabled, toggle}}
end
</code></pre>
<p>In a “component”, setting the value in the component body because I cannot be bothered to make up an event system:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">def component(hooks) do
  {hooks, {enabled, toggle}} = use_toggle(hooks)
  hooks = toggle.(hooks)
  {"&lt;div&gt;#{to_string(enabled)}&lt;/div&gt;", hooks}
end

hooks = %{array: %{}, pointer: 0}
{"&lt;div&gt;false&lt;/div&gt;", hooks} = component(hooks)
# Re-render:
hooks = %{hooks | pointer: 0}
{"&lt;div&gt;true&lt;/div&gt;", hooks} = component(hooks)
</code></pre>
<p>Obviously I am too lazy to test this so there might be mistakes, but hopefully you get the point.</p>
</blockquote>
</aside>
<p>Thanks for taking the time to sketch this out, <a class="mention" href="/u/garrison" rel="nofollow">@garrison</a>! I really appreciate the concrete example.</p>
<p>You’re right, this composes elegantly. However, the position-based approach creates some significant trade-offs. The hooks struct becomes opaque (position indices instead of semantic names), which makes it difficult to pattern match on state structure - something we’d want to preserve in any Elixir-based solution. It also inherits React’s Rules of Hooks constraints where you can’t call hooks conditionally or in different function clauses, and adding or removing hooks silently corrupts the state mapping at runtime. Additionally, debugging becomes harder when inspecting state shows <code>%{array: %{0 =&gt; value}, pointer: 1}</code> instead of meaningful names.</p>
<p>This pattern makes more sense in React’s context where JavaScript doesn’t have pattern matching to lose, DevTools can reconstruct semantic names, and there’s a massive ecosystem of hooks. In Elixir, we’d be importing React’s constraints without its benefits, while sacrificing opportunities to leverage what makes Elixir powerful.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="377115" data-batch-url="/posts/batch_likers">
                        3
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/composability-patterns-for-hologram-looking-for-your-ideas/73073/36">Post #35</a>
	                </div>
	            </div>
              <div id="likers-container-377115" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="377115"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #35"></div>
  </section>
</div>
    <div class="postbit" id="377119" data-post-id="377119">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="bartblast" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/bartblast/120/17647_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  bartblast
                    <span class="op-star" title="Thread Starter">
                      <img alt="OP" class="op-star-icon" src="/assets/thread-icons/thread-icon-thread-starter-df91e872.png" />
                    </span>
                  </h3>
		          </div>
						
			          <div class="user-title">
									<span>Creator of Hologram</span>
			          </div>
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="nikfp" data-post="35" data-topic="73073">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/nikfp/48/37207_2.png" class="avatar"> nikfp:</div>
<blockquote>
<p>Do you have an idea in mind for uniquely identifying each instance? Or at the least, preventing naming collisions through a compile time check?</p>
<p>There may also be value in having the keys dynamically generated, which would then require some kind of unique id that I would expect would relate back to the root component. Im thinking of an example where you have N list entries, and each one is represented by a component tree with a store at the top.</p>
</blockquote>
</aside>
<p>I don’t have anything tangible yet, only some abstract ideas I’m exploring.</p>
<p>I should clarify - you’re asking about stores specifically (if I understand this correctly), but I’m thinking more broadly about composability patterns in general: how actions, commands, state operations, and other behaviors could compose. Different patterns might be appropriate for different things.</p>
<p>For stores with dynamic instances (like N list entries), using the component ID (cid) for instance-level isolation makes sense. For composables in general, <code>__MODULE__</code> could provide automatic namespacing to prevent collisions, and there might be some compile-time possibilities for conflict detection in certain cases. But the solution space is still open - it’s not one-size-fits-all.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="377119" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/composability-patterns-for-hologram-looking-for-your-ideas/73073/37">Post #36</a>
	                </div>
	            </div>
              <div id="likers-container-377119" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="377119"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #36"></div>
  </section>
</div>
    <div class="postbit" id="377127" data-post-id="377127">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="venkatd" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/venkatd/120/9419_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  venkatd
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>I think it might be worth looking into how Elm (and the Gleam version Lustre) compose interfaces.<br>
These projects were what inspired the Redux pattern in React applications and is very functional in nature.</p>
<p>It’s called MVU (Model-View-Update) and is very close to how OTP works which is why I think it might give some inspiration.</p>
<p>it’s also very simple which is a plus.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="377127" data-batch-url="/posts/batch_likers">
                        3
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/composability-patterns-for-hologram-looking-for-your-ideas/73073/38">Post #37</a>
	                </div>
	            </div>
              <div id="likers-container-377127" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="377127"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #37"></div>
  </section>
</div>
    <div class="postbit" id="377130" data-post-id="377130">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="garrison" src="/assets/icons/user-9f439610.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  garrison
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>I’m sure there is no shortage of valid criticisms for porting hooks to Elixir directly, but I don’t follow yours here. The hook invocations are <em>variable declarations</em>. The resulting variables are just… variables. You can do whatever you want with them, including pattern matching.</p>
<p>The variables also <em>have semantic names</em>. Variable names! It seems to me like you are thinking of the internal “hooks” array as part of the API, but that is not the case. This is hidden internal state, just like in React. It’s not for users to mess with. I exposed it because I was showing an example <em>implementation</em>.</p>
<p>You claim that this approach obviates semantic names, but notice that it is <em>you</em> who is advocating for an approach that mutilates variables into atom keys! You are, in fact, reimplementing a language construct one level removed from the language itself.</p>
<p>Here is a declarative component:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">def banner(%{user_id: id} = props) do
  user = load_user!(id)
  show_greeting = true
  case show_greeting do
    true -&gt; "&lt;div&gt;Hello, #{user.name}&lt;/div&gt;"
    false -&gt; "&lt;div /&gt;"
  end
end
</code></pre>
<p>Now we could add hooks to keep track of state:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">def banner(%{user_id: id} = props, component) do
  {user, component} = use_memo(component, fn -&gt; load_user!(id) end, [id])
  {{show_greeting, set_show_greeting}, component} = use_state(component, false)

  template = case show_greeting do
    true -&gt; "&lt;div&gt;Hello, #{user.name}&lt;/div&gt;"
    false -&gt; "&lt;div /&gt;"
  end
  {template, component}
end
</code></pre>
<p>Frankly this approach is showing a lot more promise than I was expecting. I’m starting to think about actually attempting this.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="377130" data-batch-url="/posts/batch_likers">
                        1
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/composability-patterns-for-hologram-looking-for-your-ideas/73073/39">Post #38</a>
	                </div>
	            </div>
              <div id="likers-container-377130" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="377130"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #38"></div>
  </section>
</div>
    <div class="postbit" id="377134" data-post-id="377134">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="garrison" src="/assets/icons/user-9f439610.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  garrison
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="bartblast" data-post="36" data-topic="73073">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/bartblast/48/17647_2.png" class="avatar"> bartblast:</div>
<blockquote>
<p>inherits React’s Rules of Hooks constraints where you can’t call hooks conditionally or in different function clauses</p>
</blockquote>
</aside>
<p>I do remember thinking this way, but you must be wary of Chesterton’s Fence.</p>
<p>A React engine is a tool for writing incremental code. That is, code that can be rewinded/resumed or partially re-computed. When you write incremental code you must be extremely wary of unkeyed sets. I am particularly fond of this quote:</p>
<blockquote>
<p>…plain, old, indexed arrays are kryptonite for incremental code. Unless you’ve deliberately learned how to avoid them, you won’t get far…</p>
</blockquote>
<p><a href="https://acko.net/blog/do-it-live/" rel="noopener nofollow ugc">Source</a></p>
<p>The problem, fundamentally, is that diffing a tree without keys is <code>O(n^3)</code>. If you’re writing incremental code, this means that no matter what you do your code will always be intractably slow. The solution is to take a hint from MapReduce and put keys everywhere, all the way down the tree. This is why React has the <code>key</code> attribute, and it’s why (as of recently) LiveView has a <code>:key</code> attribute as well.</p>
<p>With React the components are the units of incremental execution and they are safely keyed. But unfortunately this means you must use a component for <em>everything</em>, like the toggle example in the OP of this thread. There is no way to factor out reusable “logic” that is <em>not</em> a component, and over time, <em>in practice</em>, this became annoying. That is why Hooks exist.</p>
<p>But Hooks don’t have keys, so how do they perform incremental reconciliation? Simple: they are forced by the “rules of hooks” to always line up. They cannot be executed conditionally or variably.</p>
<p>A choice was made to keep Hooks simpler and limit the control flow of component execution rather than to extend the keyed diff model. There are a lot of tradeoffs here and I don’t know the exact reason they made that call, but I believe the answer is <a href="https://github.com/reactjs/rfcs/pull/68" rel="noopener nofollow ugc">buried somewhere in this enormous discussion</a>.</p>
<p>I have come to appreciate the wisdom of this decision over time. If Hooks were keyed, they would effectively <em>be</em> components. But the reason Hooks exist is that, <em>in practice</em>, it seems like there are some pieces of code that are nicer when they are not components. So Hooks are a tool for writing incremental code which is <em>not</em> keyed, meaning it must have “static” control flow. Not static <em>everywhere</em>, mind you, but at the barriers where the code interacts with the rewindable state (the Hooks).</p>
<p>It’s a nice solution. I’m not against exploring the state space of alternative solutions by any means, but do try to keep in mind the reasons why things are they way they are. Hooks <em>are</em> actually pretty good glue for incremental and “regular” code.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="377134" data-batch-url="/posts/batch_likers">
                        2
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/composability-patterns-for-hologram-looking-for-your-ideas/73073/40">Post #39</a>
	                </div>
	            </div>
              <div id="likers-container-377134" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="377134"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #39"></div>
  </section>
</div>
    <div class="postbit" id="377503" data-post-id="377503">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="jam" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/jam/120/36266_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  jam
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Honestly if it wasn’t already overloaded <code>react</code> would have probably been best. Maybe <code>watch</code> or <code>track</code> but feels a little passive. Maybe <code>trigger</code>,<br>
<code>spark</code>, <code>fire</code>.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="377503" data-batch-url="/posts/batch_likers">
                        1
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/composability-patterns-for-hologram-looking-for-your-ideas/73073/41">Post #40</a>
	                </div>
	            </div>
              <div id="likers-container-377503" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="377503"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-last-post cat-last-post" title="Last post!"></div>
  </section>
</div>
</template></turbo-stream><turbo-stream action="replace" target="load-more-container"><template><div id="load-more-container" class="load-more-container">
    <span class="all-loaded">— All posts loaded —</span>
</div></template></turbo-stream>