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


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="garrison" data-post="11" data-topic="71233">
<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>That’s very clever because it side-steps the need to train developers on which type of component to use.</p>
</blockquote>
</aside>
<p>I mean, it just means they needed to be trained in a different way <img src="https://forum.elixirforum.com/images/emoji/apple/sweat_smile.png?v=15" title=":sweat_smile:" class="emoji" alt=":sweat_smile:" loading="lazy" width="20" height="20">  My first real experience with React was on a greenfield project that started roughly two weeks before hooks where officially released (which we immediately switched to) and we ended up creating a rabbit hole of side-effects (though possibly that was always a problem with React).  I suspect a lot of confusion around LiveView’s model is largely from people being used to React.  Conversely, one reason LiveView clicked quickly was having a single parent that is in control and I’m sure that has everything to do with using a similar concept back in my PHP days (“page controller” that fetched data and passed it down to “blocks”).  That was a framework created by a co-worker… there was even a way to do JS without writing any JS <img src="https://forum.elixirforum.com/images/emoji/apple/sweat_smile.png?v=15" title=":sweat_smile:" class="emoji" alt=":sweat_smile:" loading="lazy" width="20" height="20"></p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="367519" 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/complex-components-lead-to-us-always-calling-detach-hook-3-before-attach-hook-4/71233/12">Post #11</a>
	                </div>
	            </div>
              <div id="likers-container-367519" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="367519"
                     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 #11"></div>
  </section>
</div>
    <div class="postbit" id="367520" data-post-id="367520">
  <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="sodapopcan" data-post="12" data-topic="71233">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/sodapopcan/48/34668_2.png" class="avatar"> sodapopcan:</div>
<blockquote>
<p>I mean, it just means they needed to be trained in a different way</p>
</blockquote>
</aside>
<p>Oh yeah for sure, in particular you still have to be trained about when to lift state up and so on. But I think it makes it easier since there is no “component dichotomy” to worry about. And it’s nice to be able to switch between a stateless/stateful component just by adding/removing a line of code. I believe this was a design goal for them.</p>
<aside class="quote no-group" data-username="sodapopcan" data-post="12" data-topic="71233">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/sodapopcan/48/34668_2.png" class="avatar"> sodapopcan:</div>
<blockquote>
<p>Conversely, one reason LiveView clicked quickly was having a single parent that is in control</p>
</blockquote>
</aside>
<p>I would imagine this is mostly orthogonal to which framework you’re using. Having a “single parent” as you say is more a hallmark of a simple app. Of course it always feels better to work on something simple, before things spiral out of control <img src="https://forum.elixirforum.com/images/emoji/apple/slight_smile.png?v=15" title=":slight_smile:" class="emoji" alt=":slight_smile:" loading="lazy" width="20" height="20"></p>
<p>It would be perfectly valid to design a React app with a single parent holding all the state, where all other components are pure function components. But as the app gets larger this is impractical, and it’s the same way in LiveView.</p>
<p>Really LiveView is <em>very</em> similar to pre-hooks React, with a few unfortunate warts that make it compose a bit worse. I do think LiveComponents having global ids is a mistake, now. I’m not sure if it’s something that should be corrected, or if we should create a new type of component, or if we should leave LiveView as it is and build something else.</p>
<p>One path would be to add something <em>like</em> React’s hooks to function components and get rid of LiveComponents. Essentially do exactly what they did. That’s what I was alluding to, there.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="367520" 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/complex-components-lead-to-us-always-calling-detach-hook-3-before-attach-hook-4/71233/13">Post #12</a>
	                </div>
	            </div>
              <div id="likers-container-367520" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="367520"
                     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 #12"></div>
  </section>
</div>
    <div class="postbit" id="367523" data-post-id="367523">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="garrison" data-post="13" data-topic="71233">
<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>I would imagine this is mostly orthogonal to which framework you’re using. Having a “single parent” as you say is more a hallmark of a simple app. Of course it always feels better to work on something simple, before things spiral out of control <img src="https://forum.elixirforum.com/images/emoji/apple/slight_smile.png?v=15" title=":slight_smile:" class="emoji" alt=":slight_smile:" loading="lazy" width="20" height="20"></p>
</blockquote>
</aside>
<p>You would have to define “simple” here as I personally wouldn’t characterize anything I’ve worked on professionally as simple.  I don’t mean “single parent” for the whole app (ie, not “SPA”) but single parent per “page.”  At the same time, I’ve worked on an SPA-style LiveView that was pretty massive and had all the callback handlers in one place.  It’s a whole other conversation around notions of file size but I personally really liked that.  In my spaghetti PHP days we used to have an <code>actions.php</code> which just every single side-effect the app did in one file (delegating to functions calls, of course, just like <code>handle_event</code>)  I may not be properly addressing what you’re saying here, though.</p>
<p>But ya it certainly does depend on what you’ve worked on and how you like to structure things.  The React app I worked on for 2.5 years was a very complex gantt chart for scheduling shift work (the chart itself was off-the-shelf thankfully but there was a lot more to it).  It was components calling components calling components with side-effects at all levels, and too much stuff shoved into context (which is something I’m hoping HEEx never gets).  Everyone on the team was pretty competent so it wasn’t as bad as it could have been, but still not fun to work with.  I would have much rather had the giant parent controlling everything with properly composed components at the top level to reduce (or completely remove) the need for react context.</p>
<p>But ya again, I’m sure many are side-eyeing the heck out of me right now.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="367523" 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/complex-components-lead-to-us-always-calling-detach-hook-3-before-attach-hook-4/71233/14">Post #13</a>
	                </div>
	            </div>
              <div id="likers-container-367523" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="367523"
                     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 #13"></div>
  </section>
</div>
    <div class="postbit" id="367529" data-post-id="367529">
  <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="sodapopcan" data-post="14" data-topic="71233">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/sodapopcan/48/34668_2.png" class="avatar"> sodapopcan:</div>
<blockquote>
<p>You would have to define “simple” here as I personally wouldn’t characterize anything I’ve worked on professionally as simple.</p>
</blockquote>
</aside>
<p>I don’t mean that there’s some sort of “simple cutoff”, just that as complexity increases it becomes much harder to keep all of your state and business logic “in one place”, without factoring it out into abstractions. I think we all have a good idea of with simplicity and complexity <em>feel</em> like in our code, even if we can’t give an exact definition, though I know some have tried.</p>
<aside class="quote no-group" data-username="sodapopcan" data-post="14" data-topic="71233">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/sodapopcan/48/34668_2.png" class="avatar"> sodapopcan:</div>
<blockquote>
<p>but single parent per “page.”</p>
</blockquote>
</aside>
<p>It’s a bit different when you can cleanly factor things out into “pages”, as that is of course one way to break up an app. The sort of “desktop app experience” I personally covet (as you have probably noticed) doesn’t quite work this way, though, as more interactive apps tend to have the same components appear in multiple places, or all at once. There is still a notion of “screens” of course, but you need the ability to <em>compose</em> components. Generally in an old-school form-driven webapp you don’t compose pages (iframes notwithstanding…); it’s a different UX.</p>
<p>When you mention using LiveComponents for a search/select input, for example, that is a component you’re composing. But imagine you want to include an entire “new comment” form inline under a post, but also inline replying to <em>another</em> comment. You could split it off to an entire new page, but that’s a clear UX compromise.</p>
<p>You could use a function component, but let’s say it renders markdown (on the server, this is LiveView after all). So it needs state, and event handlers, and the ability to mount and unmount itself <em>declaratively</em> based on the template.</p>
<p>In the limit, if you want highly interactive apps that feel like desktop apps used to, you need components that can compose, declaratively. LiveComponents <em>almost</em> can except for the global id thing. Function components <em>definitely</em> cannot, as the OP demonstrates.</p>
<aside class="quote no-group" data-username="sodapopcan" data-post="14" data-topic="71233">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/sodapopcan/48/34668_2.png" class="avatar"> sodapopcan:</div>
<blockquote>
<p>But ya again, I’m sure many are side-eyeing the heck out of me right now.</p>
</blockquote>
</aside>
<p>Definitely not, your experience is still valid! But I think you have to keep in mind that you could just as easily recreate a spaghetti React app in LiveView if you wanted to. It would be, mostly, the same. It’s on the craftsman, not the tools <img src="https://forum.elixirforum.com/images/emoji/apple/slight_smile.png?v=15" title=":slight_smile:" class="emoji" alt=":slight_smile:" loading="lazy" width="20" height="20"></p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="367529" 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/complex-components-lead-to-us-always-calling-detach-hook-3-before-attach-hook-4/71233/15">Post #14</a>
	                </div>
	            </div>
              <div id="likers-container-367529" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="367529"
                     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 #14"></div>
  </section>
</div>
    <div class="postbit" id="367656" data-post-id="367656">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="josevalim" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/josevalim/120/1787_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  josevalim
                  </h3>
		          </div>
						
			          <div class="user-title">
									<span>Creator of Elixir</span>
			          </div>
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Hi <a class="mention" href="/u/slouchpie" rel="nofollow">@slouchpie</a>, we should probably have an option that allows you to replace the existing hook, so you don’t need to do this dance:</p>
<pre><code>|&gt; attach_hook(hook_name, lifecycle_function, &amp;handle_event_hook/3, replace: true) 
</code></pre>
<p>Which basically says that, if it already exists, replace it. A PR is very welcome (please ping me if you do). The reason we raise is to avoid accidental overlaps but in this case it is very intentional.</p>
<aside class="quote no-group" data-username="garrison" data-post="2" data-topic="71233">
<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>Which is unfair, because obviously Jose has probably seen as many LiveView apps as anyone can have seen and I’m sure he only posted about it because he had seen good results with the pattern.</p>
</blockquote>
</aside>
<p>I am very willing to accept that once we use more hooks, we will see some cracks in that approach too, but I really don’t think this thread is one of them. We have a safety in place, which is easy to bypass with detach_hook, and we can improve it further through pull requests.</p>
<p>I honestly regret writing that comment because many have read “LiveComponents being overused” as “LiveComponents being useless” while they still have many use cases. The goal was mostly to have folks discuss and evaluate alternatives.</p>
<aside class="quote no-group" data-username="endoooo" data-post="3" data-topic="71233">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/endoooo/48/25409_2.png" class="avatar"> endoooo:</div>
<blockquote>
<p>right now, I’m somewhat confused about what are good scenarios for LiveComponent vs function components. as a not so seasoned developer like you guys (and as someone coming from a non-technical background), I think more practical examples/guides would be very helpful.</p>
</blockquote>
</aside>
<p>To be clear, if you don’t have state, a function component should always be preferred over live components. When it comes to live components vs hooks though, my go-to canon is this:</p>
<ul>
<li>
<p>Live components are great for sharing parts of your application (such as a form embedded in different places, as you mentioned) or encapsulating complex parts of a page. They usually interact with specific parts of your domain.</p>
</li>
<li>
<p>Hooks are great for creating abstractions that are meant to be generic and focused more on the UI.</p>
</li>
</ul>
<p>However, it is completely fine if your team arrives to a different conclusion. The most important is what you have said before: “also motivated by discussions here with my team, we started to investigate how to refactor parts of our app”. Discuss between yourselves, try a couple of approaches, and then establish the pros and cons based on your experience in your project. And if you can share them later with the community, I am certain it will be very valuable.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="367656" data-batch-url="/posts/batch_likers">
                        5
                      </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/complex-components-lead-to-us-always-calling-detach-hook-3-before-attach-hook-4/71233/16">Post #15</a>
	                </div>
	            </div>
              <div id="likers-container-367656" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="367656"
                     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 #15"></div>
  </section>
</div>
    <div class="postbit" id="367665" data-post-id="367665">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote group-livebook_core_team" data-username="josevalim" data-post="16" data-topic="71233">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/josevalim/48/1787_2.png" class="avatar"> josevalim:</div>
<blockquote>
<ul>
<li>Live components are great for sharing parts of your application (such as a form embedded in different places, as you mentioned) or encapsulating complex parts of a page. They usually interact with specific parts of your domain.</li>
<li>Hooks are great for creating abstractions that are meant to be generic and focused more on the UI.</li>
</ul>
</blockquote>
</aside>
<p>This is so interesting, it’s the literal opposite of how I approach it <img src="https://forum.elixirforum.com/images/emoji/apple/exploding_head.png?v=15" title=":exploding_head:" class="emoji" alt=":exploding_head:" loading="lazy" width="20" height="20"></p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="367665" 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/complex-components-lead-to-us-always-calling-detach-hook-3-before-attach-hook-4/71233/17">Post #16</a>
	                </div>
	            </div>
              <div id="likers-container-367665" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="367665"
                     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 #16"></div>
  </section>
</div>
    <div class="postbit" id="367666" data-post-id="367666">
  <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 group-livebook_core_team" data-username="josevalim" data-post="16" data-topic="71233">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/josevalim/48/1787_2.png" class="avatar"> josevalim:</div>
<blockquote>
<p>I am very willing to accept that once we use more hooks, we will see some cracks in that approach too, but I really don’t think this thread is one of them.</p>
</blockquote>
</aside>
<p>I’m not entirely sure about this. The problem in the OP is a key collision, which is a direct result of this pattern not properly composing. Maybe in this case making the attach idempotent obviates the problem, but there are cases where you would want both hooks attached. I think this is a <em>symptom</em> that something is wrong, somewhere.</p>
<p>I would like to amend my first reply to this thread: I <em>do not</em> think the pattern you posted is a mistake. Actually, I think what has happened is we have discovered the very same problem the React community discovered many years ago: <a href="https://legacy.reactjs.org/docs/hooks-intro.html#its-hard-to-reuse-stateful-logic-between-components" rel="noopener nofollow ugc">you want the ability to re-use stateful logic between components</a>. When you say people are over-using LiveComponents (which I fully, 100% believe is true) I think this is a big part of why.</p>
<p>React’s solution to this problem was hooks, particularly the idea of <em>custom hooks</em>.</p>
<p>And before I continue, I should explicitly point out: the fact that React hooks and LV’s lifecycle hooks have the same name is a coincidence. The analog to React hooks here, in the pattern Jose showed, are the <em>functions</em> which register LV hooks <em>or state</em>. That is to say, the analog to a <em>React custom hook</em> in the OP is <code>AvatarComponent.attach_hooks()</code>. And in fact, React hooks are <em>also</em> functions. The name collision is unfortunate, but ironic in context! <img src="https://forum.elixirforum.com/images/emoji/apple/slight_smile.png?v=15" title=":slight_smile:" class="emoji" alt=":slight_smile:" loading="lazy" width="20" height="20"></p>
<p>Anyway, the React team went to great lengths to ensure their “re-usable functions” (which they call Hooks) are composable. The solution they went with was to make them rely on call order. They evaluated using keys, and explicitly chose not to because that approach does not compose.</p>
<p>Now, our analogs to React’s built-in hooks (e.g. <code>useState</code> and <code>useEffect</code>) are <code>assign()</code> and <code>attach_hook()</code>. They both use keys, and I don’t think LiveView is going to get away from that choice at this point. And I’m not saying we should have used call order, either. That solution does not “feel right” to me, for Elixir, and I suspect many would agree.</p>
<p>So we need some way to make these “re-usable stateful functions”, which by the way we should really come up with a name for (<em>not Hooks lol</em>), compose. Since we’re pretty set on keys already, a good solution would be to namespace them somehow. Preferably this would be done <em>mostly</em> automatically.</p>
<p>I’m not sure what an API for this would actually look like. I’d be very curious to hear what others think. Perhaps some way to call a function like <code>MyModule.attach_hooks_and_state()</code> which receives a namespaced <code>socket</code> with its assigns/hooks encapsulated somehow, similar to how a LiveComponent receives an “editorialized” socket.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="367666" 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/complex-components-lead-to-us-always-calling-detach-hook-3-before-attach-hook-4/71233/18">Post #17</a>
	                </div>
	            </div>
              <div id="likers-container-367666" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="367666"
                     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 #17"></div>
  </section>
</div>
    <div class="postbit" id="367668" data-post-id="367668">
  <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 group-livebook_core_team" data-username="josevalim" data-post="16" data-topic="71233">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/josevalim/48/1787_2.png" class="avatar"> josevalim:</div>
<blockquote>
<p>I honestly regret writing that comment because many have read “LiveComponents being overused” as “LiveComponents being useless” while they still have many use cases. The goal was mostly to have folks discuss and evaluate alternatives.</p>
</blockquote>
</aside>
<p>BTW, I don’t think you should regret the post. It seems to me that it was quite successful, seeing as we’re discussing alternatives right now! <img src="https://forum.elixirforum.com/images/emoji/apple/slight_smile.png?v=15" title=":slight_smile:" class="emoji" alt=":slight_smile:" loading="lazy" width="20" height="20"></p>
<p>I am curious what others think of the idea of finding a way to add <em>optional</em> state to otherwise pure functions. Another advantage of React’s hook approach (as I mentioned somewhere above) is that they got rid of the dichotomy of “class/function” components, which seems to be a problem we’re dealing with here.</p>
<p>I think the biggest argument against would be that, since Elixir functions are (generally) <em>actually</em> pure, we would be violating that mental model by mounting state within them. On the other hand, that’s essentially what LiveComponents are doing, and we get by, so I’m not sure.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="367668" 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/complex-components-lead-to-us-always-calling-detach-hook-3-before-attach-hook-4/71233/19">Post #18</a>
	                </div>
	            </div>
              <div id="likers-container-367668" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="367668"
                     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>