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


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="MarthinL" src="/assets/icons/user-9f439610.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  MarthinL
                    <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>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="garrison" data-post="27" data-topic="69023">
<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>
<pre data-code-wrap="elixir"><code class="lang-elixir">%{
  id: 1, type: :folder, name: "elixir stuff", children: [
    %{id: 2, type: :file, name: "elixir.jpg"},
  ],
}
</code></pre>
</blockquote>
</aside>
<p>For reference sake, the structure part for that (in the form I current use, which might change at will) looks like this:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">[{1,[2]}]
</code></pre>
<p>But that only works if it really is a recursive structure, i.e. if every id refers to a record in the exact same schema. For my data that holds true, but in your example you have separate schemas for files and folders. I guess though that it’s merely a consequence of the oversimplification of the example you’ve constructed. I too have very many schemas involved in the node, and I need and load them all for the components to turn into HTML. I count all of that as one node with one id of the recursive schema which eventually gets to a list of records (with ids) of the same schema again. Those would be the next (child) ids that goes into the tree structure. Nothing else.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="354925" 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/using-streams-with-recursive-and-or-deeply-nested-schemas/69023/32">Post #31</a>
	                </div>
	            </div>
              <div id="likers-container-354925" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="354925"
                     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="354929" data-post-id="354929">
  <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="MarthinL" data-post="30" data-topic="69023">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/letter_avatar_proxy/v4/letter/m/3da27b/48.png" class="avatar"> MarthinL:</div>
<blockquote>
<p>You’re storing the simplified tree still in nested maps</p>
</blockquote>
</aside>
<p>My comment had grown long so I was not as clear about this as I should be. I am essentially storing <em>two copies</em> of the tree. The first is a tree of <code>Node</code>s which comes from the database (loaded via recursive query from Postgres), and then the maps of <code>folders</code> and (in our example) <code>files</code> which go with it. (If you will recall my real app is for RSS feeds, not files, but this is immaterial.)</p>
<p>Then there is a second form, which is stored <em>alongside</em> the first. More specifically, it is <em>recomputed from the first</em> each time either the tree structure <em>or</em> any of the maps (<code>files</code>, <code>folders</code>) changes in response to a PubSub broadcast.</p>
<p>This <em>second</em> form, which again lives alongside the first form, is the “simplified tree” I described (when I came up with this design I called it a “rendered tree”, but I am trying to avoid overloading that term in this conversation).</p>
<p>The purpose of the “simplified tree” is twofold: first, it materializes the changes which come in from the PubSub, which in my case is very important because a change in a single record can actually affect many places in the tree. This may not apply to you, but again my UI is highly interactive.</p>
<p>The second purpose is that the LiveComponents actually need this materialized structure to properly diff their own attributes. If you imagine the alternative - passing the <code>files</code> and <code>folders</code> maps down to each LiveComponent along with the tree - you will find that updating the maps can have performance problems because LiveView is not (or at least was not when I tried) smart enough to diff these arbitrary map accesses at runtime.</p>
<p>So, by passing a “simplified tree” to the LiveComponents instead, they are able to easily see <em>exactly</em> which attributes have changed since the last version, and as a result the diffs are <em>very</em> minimal.</p>
<p>Honestly, thinking about it now, I think the best name would be “materialized tree”. I’m afraid that may be the third or fourth name I’ve given it over the course of this discussion…</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="354929" 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/using-streams-with-recursive-and-or-deeply-nested-schemas/69023/33">Post #32</a>
	                </div>
	            </div>
              <div id="likers-container-354929" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="354929"
                     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="354934" data-post-id="354934">
  <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>This is a lot to comprehend so here’s a purely “visual” example:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir"># Tree structure
root_node = %Node{
  id: 1, parent_id: nil, folder_id: 1, file_id: nil,
  children: [
    %Node{id: 2, parent_id: 1, folder_id: nil, file_id: 1},
    %Node{id: 3, parent_id: 1, folder_id: nil, file_id: 2},
  ],
}
# Folders
folders = %{
  1 =&gt; %Folder{id: 1, name: "Elixir stuff"},
}
# Files
files = %{
  1 =&gt; %File{id: 1, name: "elixir.jpg"},
  2 =&gt; %File{id: 2, name: "jose.png"},
}
</code></pre>
<p>Then we have a recursive function, <code>materialize/3</code>, to “materialize” the tree.</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">def materialize(%Node{file_id: nil} = node, folders, files) do
  %{
    id: node.id, type: :folder,
    name: Map.fetch!(folders, node.folder_id).name,
    children: Enum.map(node.children, &amp;materialize(&amp;1, folders, files)),
  }
end

def materialize(%Node{folder_id: nil} = node, folders, files) do
  %{
    id: node.id, type: :file,
    name: Map.fetch!(files, node.file_id).name,
  }
end
</code></pre>
<p>Which would produce the following “materialized tree”, which we pass to our LiveComponents.</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">%{
  id: 1, type: :folder, name: "Elixir stuff",
  children: [
    %{id: 2, type: :file, name: "elixir.jpg"},
    %{id: 3, type: :file, name: "jose.png"},
  ],
}
</code></pre>
<p>So now, if we received a new folder over PubSub, we would essentially do this:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">def handle_info({:folder_updated, %Folder{} = new_folder}, socket) do
  %{root_node: root_node, folders: folders, files: files} = socket.assigns

  folders = Map.put(folders, new_folder.id, new_folder)
  mtree = materialize(root_node, folders, files)
  socket = assign(socket, folders: folders, materialized_tree: mtree)

  {:noreply, socket}
end
</code></pre> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="354934" 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/using-streams-with-recursive-and-or-deeply-nested-schemas/69023/34">Post #33</a>
	                </div>
	            </div>
              <div id="likers-container-354934" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="354934"
                     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="354991" data-post-id="354991">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="MarthinL" src="/assets/icons/user-9f439610.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  MarthinL
                    <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>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Before I can start processing your constructed example I need to first ask this: You refer to two structures, at least in the simplified form both containing a type and a name with the only difference whether or not it has children. Do you really require two types and two structures in order for the sample to remain relevant to your actual data, or can we exploit the notion that the only difference between the two we care about is whether or not it has any children?</p>
<p>If that would be fair to say you don’t need to keep a type and always have a children field which if it’s nil or <span class="chcklst-box fa fa-square-o"></span> (your choice) it means a type of file and if there are children it means type is folder.</p>
<p>In case it’s what you’re thinking, no, it’s not nitpicking from my side but an important distinction. See, in my interpretation of recursive trees if files are it’s own type then the list of files in a folder would be considered straight node contents and not form part of the recursive structure. The structure exlusively concerns itself with actually recursive content, i.e. folders with folders as children (i.e. subfolders) n-levels deep.</p>
<p>If your tree is recursive in multiple dimensions, i.e. on top of folders having some files and some folders, files may also have sub-files and sub-folders too. even though that’s not how your example is set up (although in reality it’s what happens with zip files when they’re seen as folders in like a file manager) if that’s closer to how your actual data is structured, then you are most likely justified in keeping your materialised view in the manner you describe.</p>
<p>I too have built two kinds of recursion into my srtucture. But I present them differently to the user, only one of which involves an actual tree view while for the other I have novel (custom) nested representations I’ve come up with as key enabling concepts for my app. I handle them independently even though they all interconnect to form the massive globally distributed dataset. This is all part of the pre-work in design I’ve mentioned whereby the user experiences nothiing of the ovewhelming volume and complex nature of the underlying data. What the user sees can be extremely simple if they choose, or they can explore and manage as much detail and complexity as they feel comfortable dealing with for a while before they encapsulate the complexity again behind a synopsis of their choosing.</p>
<p>The point being that rather than talking in circles around an irrelevant example, I’d rather first understand if your data and my data share sufficient strucural similarities to allow for a common solution.</p>
<p>I believe we’ve already established one potentially viable option with regards to controlling partial updates by using LiveComponents, and that keeping structural data on its own (as a stripped-down copy or in another form) in session state enables better change detection, propagation and handling without the (memory and/or) bandwidth cost of keeping a fully populated tree in memory.</p>
<p>Unless our datasets follow the same or very similar recursive principles putting implementation details under a stronger microscope could see us talking cross-purposes. That would become counter-productive, frustrating and an unnecessary distraction for one or both of us. It’s very useful to feed off each other’s insights, eperiences, learning and where possible to discover and leverage relevant options and opportunities and hopefully follow aligned approaches, but it is not important that we use the same code or structures to do so.</p>
<p>My user interface is also highly interactive but in all likelihood in fundamentally different ways than yours. One key difference I see already is that your data is born externally (as RSS feeds) which you’re helping the user track and make sense of by doing as much interpretation of the data as you can muster on behalf of the users, while my point of departure is that the data is born internally (each user’s own) and connected to external data only through the individual (human) interpretation of users. That might be inaccurate or immaterial as a difference, or it could be the core reason why the datasets we use are and must be structured, presented and manipulated differently. I doubt we have the capacity to learn all about each other’s data and use-cases to find that out, so my suggestion is that we keep discussing general principles and opportunities on the abstract level rather than get too caught up contriving an example which represent both our use-cases without directly being either.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="354991" 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/using-streams-with-recursive-and-or-deeply-nested-schemas/69023/35">Post #34</a>
	                </div>
	            </div>
              <div id="likers-container-354991" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="354991"
                     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="354992" data-post-id="354992">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="MarthinL" src="/assets/icons/user-9f439610.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  MarthinL
                    <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>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="garrison" data-post="34" data-topic="69023">
<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 would produce the following “materialized tree”, which we pass to our LiveComponents.</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">%{
  id: 1, type: :folder, name: "Elixir stuff",
  children: [
    %{id: 2, type: :file, name: "elixir.jpg"},
    %{id: 3, type: :file, name: "jose.png"},
  ],
}
</code></pre>
</blockquote>
</aside>
<p>If we must discuss detail, this would be where your example departs from what we’ve been discussing. If there is a LiveComponent per node it should not (need to) be passed the entire tree but only ever a node’s worth of data at a time. It’s OK to keep the strucural part of the tree (which you call the materialised tree) in memory, but only once for a specific user session’s currently visible portion of the data. There should not be a copy of it in every node.</p>
<aside class="quote no-group" data-username="garrison" data-post="34" data-topic="69023">
<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>So now, if we received a new folder over PubSub, we would essentially do this:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">def handle_info({:folder_updated, %Folder{} = new_folder}, socket) do
  %{root_node: root_node, folders: folders, files: files} = socket.assigns

  folders = Map.put(folders, new_folder.id, new_folder)
  mtree = materialize(root_node, folders, files)
  socket = assign(socket, folders: folders, materialized_tree: mtree)

  {:noreply, socket}
end
</code></pre>
</blockquote>
</aside>
<p>Doesn’t this translate into exactly what we’ve been trying to avoid, i.e. if the a branch of the tree changes then the entire branch is rerendered and propagated?</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="354992" 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/using-streams-with-recursive-and-or-deeply-nested-schemas/69023/36">Post #35</a>
	                </div>
	            </div>
              <div id="likers-container-354992" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="354992"
                     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="355005" data-post-id="355005">
  <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="MarthinL" data-post="36" data-topic="69023">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/letter_avatar_proxy/v4/letter/m/3da27b/48.png" class="avatar"> MarthinL:</div>
<blockquote>
<p>If there is a LiveComponent per node it should not (need to) be passed the entire tree</p>
</blockquote>
</aside>
<p>When you render a recursive structure, the function to render that structure is also recursive. For example, you might have the following component to render a tree (note that this is not a LiveComponent, just an example):</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">def tree(%{node: _} = assigns) do
  ~H"""
  &lt;div&gt;
    &lt;h2&gt;&lt;%= @node.name %&gt;&lt;/h2&gt;
    &lt;div class="children"&gt;
      &lt;.tree :for={c &lt;- @node.children} node={c} /&gt;
    &lt;/div&gt;
  &lt;/div&gt;
  """
end
</code></pre>
<p>And so, you see, you have to pass the entire tree to the root node, and each successive child gets a subset of the tree to render, recursively.</p>
<aside class="quote no-group" data-username="MarthinL" data-post="36" data-topic="69023">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/letter_avatar_proxy/v4/letter/m/3da27b/48.png" class="avatar"> MarthinL:</div>
<blockquote>
<p>Doesn’t this translate into exactly what we’ve been trying to avoid, i.e. if the a branch of the tree changes then the entire branch is rerendered and propagated?</p>
</blockquote>
</aside>
<p>This question is encouraging to me, as I think you’re starting to build a good intuition for the rendering process. But your understanding is still not quite right.</p>
<p>For the example I just gave (the <code>&lt;tree /&gt;</code> component), <strong>you are correct</strong>. Because function components can’t diff arbitrary collections (like the <code>children</code> lists), the whole thing would be sent back down the wire.</p>
<p><strong>This is where the LiveComponents come in.</strong> If you rewrote that <code>&lt;tree /&gt;</code> component to be a <code>LiveComponent</code> instead, each node in the tree would diff-track its own assigns, so only a minimal diff would be sent down the wire for exactly what changed between the previous and current “materialized tree”.</p>
<p>Note that the entire thing is always “re-rendered” on the server, there’s nothing you can do about that (it’s how LiveView works, and it’s how React works too for the record).</p>
<p>But what you <em>can</em> control is the size of the diff sent down the wire, by using LiveComponents.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="355005" 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/using-streams-with-recursive-and-or-deeply-nested-schemas/69023/37">Post #36</a>
	                </div>
	            </div>
              <div id="likers-container-355005" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="355005"
                     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="355006" data-post-id="355006">
  <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="MarthinL" data-post="35" data-topic="69023">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/letter_avatar_proxy/v4/letter/m/3da27b/48.png" class="avatar"> MarthinL:</div>
<blockquote>
<p>You refer to two structures, at least in the simplified form both containing a type and a name with the only difference whether or not it has children.</p>
</blockquote>
</aside>
<p>I designed this example to be understood, try not to take it too literally.</p>
<p>If you are wondering, my real trees contain many more fields than just a <code>name</code>. Things like icons, collapsed state, and statistics like unread counts that have to be recursively calculated as I “materialize” the tree. I also deliberately left the door open for more than just two “types” because I may want to put other things in the tree in the future (collections of bookmarks, for instance).</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="355006" 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/using-streams-with-recursive-and-or-deeply-nested-schemas/69023/38">Post #37</a>
	                </div>
	            </div>
              <div id="likers-container-355006" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="355006"
                     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="355045" data-post-id="355045">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="MarthinL" src="/assets/icons/user-9f439610.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  MarthinL
                    <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>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="garrison" data-post="38" data-topic="69023">
<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>If you are wondering, my real trees contain many more fields than just a <code>name</code>. Things like icons, collapsed state, and statistics like unread counts that have to be recursively calculated as I “materialize” the tree. I also deliberately left the door open for more than just two “types” because I may want to put other things in the tree in the future (collections of bookmarks, for instance).</p>
</blockquote>
</aside>
<p>I didn’t wonder too much about it but my silent assumption (ass, u, me) was indeed incorrect. In terms I’ve heard you use your materialised tree is orthogonal to what I’ve been describing as the recursive portion of the data that’s been reduced to just an id per node and separated from the rest of the informational content. Thanks for pointing that out, at least we can stop talking past each other a little bit better 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="355045" 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/using-streams-with-recursive-and-or-deeply-nested-schemas/69023/39">Post #38</a>
	                </div>
	            </div>
              <div id="likers-container-355045" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="355045"
                     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="355082" data-post-id="355082">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="MarthinL" src="/assets/icons/user-9f439610.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  MarthinL
                    <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>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote group-Phoenix-Core-Team" data-username="steffend" data-post="14" data-topic="69023">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/steffend/48/20548_2.png" class="avatar"> steffend:</div>
<blockquote>
<p>I hope this clarifies things a bit. Let me know if you have further questions!</p>
</blockquote>
</aside>
<p>Hi <a class="mention" href="/u/steffend" rel="nofollow">@steffend</a>, I’ve been playing arund with your example to understand it better, but my changes keeps breaking the “Load Children” button. I then went and added debug statements to see which of the two update clauses fires when, but even using your original version the first update clause never gets called, always only the second clause.</p>
<p>Can I ask you to just talk me through what that first update clause is meant to achieve and how it’s supposed to go about doing that? Specifically, the code</p>
<blockquote>
<p>(assigns, %{assigns: %{entry: _}} = socket)<br>
is so far outside my frame of reference I just can’t seem to undestand it. The only assigns that ever shows up in the socket is the one for :myself.</p>
</blockquote>
<p>The worst part is of course that you code seems to works as advertised without ever matching on that first clause, but when I change how the tree is rendered from simply nested ul’s to using a nested</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">    &lt;details&gt;&lt;summary&gt;{@entry.name}&lt;/summary&gt;
       &lt;ul&gt;
            ...
       &lt;/ul&gt;
    &lt;/details&gt;
</code></pre>
<p>construct it fails. It seems like the correct HTML gets generated (i.e. a new version of “subfolder 2” without the button but with a single child “more.txt”, but instead of just adding the child or at worst updating both the parent and the child, the result I get is that the original “subfolder 2” with button below it is left untouched but it gets a duplicate “subfolder 2” with “more.txt” child added to it. I can “at a stretch” imagine the result I see being cause by the code of the second update clause, but I cannot figure out why that same code works for your test case and not for mine.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="355082" 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/using-streams-with-recursive-and-or-deeply-nested-schemas/69023/40">Post #39</a>
	                </div>
	            </div>
              <div id="likers-container-355082" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="355082"
                     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="355086" data-post-id="355086">
  <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="MarthinL" data-post="40" data-topic="69023">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/letter_avatar_proxy/v4/letter/m/3da27b/48.png" class="avatar"> MarthinL:</div>
<blockquote>
<p>Can I ask you to just talk me through what that first update clause is meant to achieve and how it’s supposed to go about doing that?</p>
</blockquote>
</aside>
<p>You may get a better reply but briefly, the purpose of that first <code>update/2</code> clause is to receive the updated <code>entry</code> from <code>send_update/2</code>. In the example the main LiveView receives an updated <code>entry</code> over PubSub and dispatches it to the relevant LiveComponent.</p>
<p>If you are not using that <code>send_update/2</code> functionality then that update clause won’t be called because there is nothing to trigger a re-render of the components at all (they are all rendered as nested streams, once).</p>
<aside class="quote no-group" data-username="MarthinL" data-post="39" data-topic="69023">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/letter_avatar_proxy/v4/letter/m/3da27b/48.png" class="avatar"> MarthinL:</div>
<blockquote>
<p>what I’ve been describing as the recursive portion of the data that’s been reduced to just an id per node and separated from the rest of the informational content</p>
</blockquote>
</aside>
<p>I’m wondering - how do you plan to render the “informational content” which you are storing separately?</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="355086" 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/using-streams-with-recursive-and-or-deeply-nested-schemas/69023/41">Post #40</a>
	                </div>
	            </div>
              <div id="likers-container-355086" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="355086"
                     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 #40"></div>
  </section>
</div>
</template></turbo-stream><turbo-stream action="replace" target="load-more-container"><template><div id="load-more-container" class="load-more-container">
    <a class="load-more-button" data-turbo-stream="true" href="/topics/69023/load_more?page=5">Load more posts (34 remaining)</a>
</div></template></turbo-stream>