|
1 | 1 | --- |
2 | 2 | uid: trigger-renders |
3 | | -title: Triggering a Render Life-Cycle on a Component |
| 3 | +title: Triggering a Render Life Cycle on a Component |
4 | 4 | --- |
5 | 5 |
|
6 | | -# Triggering a Render Life-Cycle on a Component |
| 6 | +# Triggering a Render Life Cycle on a Component |
7 | 7 |
|
8 | | -Describe how to trigger an explicit render life-cycle through the IRenderedComponent Render, SetParametersAndRender, and InvokeAsync methods. |
| 8 | +When a component under test is rendered, an instance of the <xref:Bunit.IRenderedComponent`1> type is returned. Through that, it is possible to cause the component under test to render again directly through the <xref:Bunit.IRenderedComponentBase`1.Render> method or one of the [`SetParametersAndRender(...)`](xref:Bunit.IRenderedComponentBase`1.SetParametersAndRender(Bunit.Rendering.ComponentParameter[])) methods or indirectly through the <xref:Bunit.IRenderedFragmentBase.InvokeAsync(System.Action)> method. |
| 9 | + |
| 10 | +> [!WARNING] |
| 11 | +> The `Render()` and `SetParametersAndRender()` methods are not available in the <xref:Bunit.IRenderedFragment> type that is returned when calling the _non_-generic version of `GetComponentUnderTest()` in `<Fixture>`-based Razor tests. Call the generic version of `GetComponentUnderTest<TComponent>()` to get a <xref:Bunit.IRenderedComponent`1>. |
| 12 | +
|
| 13 | +> [!NOTE] |
| 14 | +> These methods are available and work the same in both C# and Razor-based tests. The examples below are from C# based tests only. |
| 15 | +
|
| 16 | +Let's look at how to use each of these methods to cause a re-render. |
| 17 | + |
| 18 | +## Render |
| 19 | + |
| 20 | +The <xref:Bunit.IRenderedComponentBase`1.Render> tells the renderer to re-render the component, i.e. go through its life-cycle methods (except for `OnInitialized()` and `OnInitializedAsync()` methods). To use it, do the following: |
| 21 | + |
| 22 | +[!code-csharp[](../../../samples/tests/xunit/ReRenderTest.cs?start=17&end=24&highlight=6)] |
| 23 | + |
| 24 | +The highlighted line shows the call to <xref:Bunit.IRenderedComponentBase`1.Render>. |
| 25 | + |
| 26 | +> [!TIP] |
| 27 | +> The number of renders a component has been through can be inspected and verified using the <xref:Bunit.IRenderedFragmentBase.RenderCount> property. |
| 28 | +
|
| 29 | +## SetParametersAndRender |
| 30 | + |
| 31 | +The [`SetParametersAndRender(...)`](xref:Bunit.IRenderedComponentBase`1.SetParametersAndRender(Bunit.Rendering.ComponentParameter[])) methods tells the renderer to re-render the component with new parameters, i.e. go through its life-cycle methods (except for `OnInitialized()` and `OnInitializedAsync()` methods), passing the new parameters to the `SetParametersAsync()` method, _but only the new parameters_. To use it, do the following: |
| 32 | + |
| 33 | +[!code-csharp[](../../../samples/tests/xunit/ReRenderTest.cs?start=31&end=42&highlight=8-10)] |
| 34 | + |
| 35 | +The highlighted line shows the call to <xref:Bunit.IRenderedComponentBase`1.SetParametersAndRender(System.Action{Bunit.ComponentParameterBuilder{`0}})>, which is also available as <xref:Bunit.IRenderedComponentBase`1.SetParametersAndRender(Bunit.Rendering.ComponentParameter[])> if you prefer that method of passing parameters. |
| 36 | + |
| 37 | +> [!NOTE] |
| 38 | +> Passing parameters to components through the [`SetParametersAndRender(...)`](xref:Bunit.IRenderedComponentBase`1.SetParametersAndRender(Bunit.Rendering.ComponentParameter[])) methods are identical to doing it with the [`RenderComponent<TComponent>(...)`](xref:Bunit.IRenderedComponentBase`1.SetParametersAndRender(Bunit.Rendering.ComponentParameter[])) methods, described in detail on the <xref:passing-parameters-to-components> page. |
| 39 | +
|
| 40 | +## InvokeAsync |
| 41 | + |
| 42 | +Invoking methods on a component under test, which causes a render, e.g. by calling `StateHasChanged`, can result in the following error: |
| 43 | + |
| 44 | +> The current thread is not associated with the Dispatcher. Use InvokeAsync() to switch execution to the Dispatcher when triggering rendering or component state. |
| 45 | +
|
| 46 | +If you receive this error, you need to invoke your method inside an `Action` delegate passed to the <xref:Bunit.IRenderedFragmentBase.InvokeAsync(System.Action)> method. |
| 47 | + |
| 48 | +Consider the `<ImparativeCalc>` component listed below: |
| 49 | + |
| 50 | +[!code-html[ImparativeCalc.razor](../../../samples/components/ImparativeCalc.razor)] |
| 51 | + |
| 52 | +To invoke the `Calculate()` method on the component instance, do the following: |
| 53 | + |
| 54 | +[!code-csharp[](../../../samples/tests/xunit/ReRenderTest.cs?start=49&end=56&highlight=6)] |
| 55 | + |
| 56 | +The highlighted line shows the call to <xref:Bunit.IRenderedFragmentBase.InvokeAsync(System.Action)>, which is passed an `Action` delegate, that calls the `Calculate` method. |
| 57 | + |
| 58 | +> [!TIP] |
| 59 | +> The instance of a component under test is available through the <xref:Bunit.IRenderedComponentBase`1.Instance> property. |
0 commit comments