Summary
PDTable fetches from its DataProvider only once, in OnAfterRenderAsync(firstRender) when AutoLoad is true. If the parent later supplies a different DataProvider instance to the same PDTable, nothing reloads: the table keeps rendering the rows it loaded from the previous provider until the component is recreated (for example by a full page reload).
Why it matters
This is easy to hit without noticing. Any parent that renders a PDTable inside a list, and builds a provider per item, gets its PDTable instances reused positionally by Blazor's diff when the list changes. Each reused table is handed its new provider and silently keeps showing the old data. Nothing throws, and the surrounding markup (headings, counts) updates correctly, so the page presents one item's rows under another item's heading.
Reproduction
- Render
<PDTable TItem="Row" DataProvider="@_provider" AutoLoad="true"> with _provider returning rows A, B.
- After it has loaded, set
_provider to a new instance returning rows C, D, E and re-render the parent.
- Expected: the table shows C, D, E.
- Actual: the table still shows A, B.
A bUnit test shows it directly: render with provider 1, wait for its rows, call cut.Render(p => p.Add(x => x.DataProvider, provider2)), and the rendered rows are still provider 1's.
Workaround in use
The consumer tracks the provider it last loaded, and when the parameter changes to a different instance it calls RefreshAsync() in OnAfterRenderAsync, followed by StateHasChanged(). The StateHasChanged() is needed too: RefreshAsync() refetches but does not re-render the table (the first-render path calls StateHasChanged() explicitly for the same reason).
Suggested fix
In PDTable.OnParametersSet (or SetParametersAsync), detect that DataProvider has changed by reference after the first load and schedule a reload after the next render, resetting paging to the first page. It would also be worth considering whether RefreshAsync() should call StateHasChanged() itself, since a caller that refreshes from outside the render cycle otherwise sees nothing change.
Summary
PDTablefetches from itsDataProvideronly once, inOnAfterRenderAsync(firstRender)whenAutoLoadis true. If the parent later supplies a differentDataProviderinstance to the samePDTable, nothing reloads: the table keeps rendering the rows it loaded from the previous provider until the component is recreated (for example by a full page reload).Why it matters
This is easy to hit without noticing. Any parent that renders a
PDTableinside a list, and builds a provider per item, gets itsPDTableinstances reused positionally by Blazor's diff when the list changes. Each reused table is handed its new provider and silently keeps showing the old data. Nothing throws, and the surrounding markup (headings, counts) updates correctly, so the page presents one item's rows under another item's heading.Reproduction
<PDTable TItem="Row" DataProvider="@_provider" AutoLoad="true">with_providerreturning rows A, B._providerto a new instance returning rows C, D, E and re-render the parent.A bUnit test shows it directly: render with provider 1, wait for its rows, call
cut.Render(p => p.Add(x => x.DataProvider, provider2)), and the rendered rows are still provider 1's.Workaround in use
The consumer tracks the provider it last loaded, and when the parameter changes to a different instance it calls
RefreshAsync()inOnAfterRenderAsync, followed byStateHasChanged(). TheStateHasChanged()is needed too:RefreshAsync()refetches but does not re-render the table (the first-render path callsStateHasChanged()explicitly for the same reason).Suggested fix
In
PDTable.OnParametersSet(orSetParametersAsync), detect thatDataProviderhas changed by reference after the first load and schedule a reload after the next render, resetting paging to the first page. It would also be worth considering whetherRefreshAsync()should callStateHasChanged()itself, since a caller that refreshes from outside the render cycle otherwise sees nothing change.