-
Notifications
You must be signed in to change notification settings - Fork 10.3k
RenderFragments re-rendering and state #15077
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Thank you for filing this issue. In order for us to investigate this issue, please provide a minimalistic repro project (ideally a GitHub repo) that illustrates the problem. |
@mkArtakMSFT : Thank you for taking the time to investigate. Here is the github repo: https://github.com/Postlagerkarte/renderfragment |
Probably you have to use |
Thank you @Andrzej-W - I already played around with the key attribute before filling the issue but now I tried again and got it to work, I was confused because if you render like this there is no way to set the key attribute in the foreach loop:
Wrapping it in an extra div and it works:
@mkArtakMSFT : I assume that there is no way to improve the rendering internally so that there is no need to use key attribute in the first place? |
Unfortunately adding a key only keeps the state of the renderfragment if the fragments stays within one output zone. I updated the git hub repository (https://github.com/Postlagerkarte/renderfragment) to show the problem. The fragments are still losing their state - even though the key property is assigned. Basically the code looks like this now:
and the Output.razor:
|
@Postlagerkarte Thanks for providing the repro. The problem is that you are passing a RenderFragment to a component (Zone1,Zone2,N) and then passing that same through an alternative mechanism to the output component. The problem is that RenderFragment is not a stateful UI piece of UI, but a function that represents the UI that needs to be rendered. In your OutputComponent you are simply retrieving that function and re-running it, which re-creates the UI from scratch, hence loosing the previous state (as expected). You can't reuse the same component instance in two separate places of the UI, the best alternative you have is to pass in the data from a model and keep the state out of the component. Hope this helps. |
@javiercn : Thank you for taking the time to reply. The context of my question is a drag and drop library I created in which a users can wrap anything in a draggable component and thus can drop it to an arbitrary dropzone. This works like this:
For a single dropzone the components keep their state even when re-arranged and re-rendered. ( due to the use of the key attribute) See here: https://blazordragdrop.azurewebsites.net/Components for a demo or here for the repo https://github.com/Postlagerkarte/blazor-dragdrop I am pointing that out because you wrote :
However this is not the case in the above sample - the state is only lost when I add a second dropzone. It seems the state is lost when a different parent component id is detected by the renderer and thus getcomponentstate can not find the state? Would greatly appreactiate if you can elaborate a bit more on the situation and on any workaround because this problem basically renders my library unusable for stateful components. Thank you! |
@javiercn : Sorry to post again, just want to clarify my above posting: My main question is: "RenderFragment is not a stateful UI piece of UI" - which implies you can't pass it around and expect the state to survive it. But why does this work and keeps the state:
Where as this doesn't work and the state is lost:
|
Because keys don't expand multiple components. The Blazor diff algorithm diffs component tree's individually. In the first case, there is a component tree that looks something like
While in the second case I understand each fragment is enclosed within a component
|
I am having a question about render fragments.
My setup looks like this:
I created a component called Zone.razor which contains this code:
I created another component called Output.razor which renders the fragments:
The ZoneSerive.cs is just keeping a List with the RenderFragments.
My index.razor looks like this
The
<output>
component renders the desired output , two counter components, and the components are working fine.However, If a StateHasChanged event triggers re-rendering the state of the counter components are lost.
Is this supposed to happen?
Can you advise how to keep the state upon re-rendering?
The text was updated successfully, but these errors were encountered: