1
votes

I've a general question concerning the parameters setting lifecycle for a Blazor component.

I've made a ordinary two way binding on my component. When I tested out this binding, it first seemed that nothing happens on changing the parameter value. But during debbung i noticed that indeed all binding steps are completed successfully. The bound parameter has a correct value on the parent component and the child component.

Now the strange thing comes in. I did not run the debugger to the end. I only stepped forward and saw that the property of the child component is set again with the original value. So I browsed my whole repository for the trigger of the setter. Now I decided to override the SetParameterAsync Method on my child component. Then I saw a frame which sets my property with the old value.

And now my question. Does anybody know a way to figure out which code or component sets the property. Do I have any object where I can watch the initiator of the parameter set operation?

2

2 Answers

0
votes

on changing the parameter value

You're not supposed to change your parameter value. A parameter property is an auto property. You don't change its value. Only the parent component is supposed to alter its value.

Your child component should look like this:

ChildComponent.razor

<p><input type="text" @bind="BoundValue" @bind:event="oninput" /></p>

<p>
    <button @onclick="ChangeValue">Change from Child</button>
</p>



@code {
    [Parameter]
    public string Property { get; set; }

    [Parameter]
    public EventCallback<string> PropertyChanged { get; set; }

    private string BoundValue
    {
        get => Property;
        set => PropertyChanged.InvokeAsync(value);
    }

    private Task ChangeValue()
    {
        return PropertyChanged.InvokeAsync($"New value set in Child {DateTime.Now}");
    }
} 

And your parent component may look like this:

@page "/"


<ChildComponent @bind-Property="MyProperty"/>

<p>MyProperty: @MyProperty</p>

@code 
{
    private string MyProperty { get; set; } = "Value sent to the child.";
} 

Note that the parameter property named Property in the child component is never altered. This is how you should code.

As you can understand by now, only the parent component should alter the parameter value, not the child. This explains why your property is assigned with the old value. To be more specific, when your parent component re-renders under a couple of conditions. The following is from the docs:

A child component receives new parameter values that possibly overwrite existing values when the parent component rerenders. Accidentially overwriting parameter values in a child component often occurs when developing the component with one or more data-bound parameters and the developer writes directly to a parameter in the child:

The child component is rendered with one or more parameter values from the parent component. The child writes directly to the value of a parameter. The parent component rerenders and overwrites the value of the child's parameter. More here

Note: Debugging can't help you much is this respect... Note also that Blazor has specific algorithm that determines which types should be overwritten and under what conditions. Debugging won't help you much. It will only confuse you and lead you to believe that Blazor is buggish software. But what is going on here is by design...

1
votes

As you've not provided any specifics, I'll describe want I do when debugging thorny issues in components.

  1. Override on all the component events and see how often they get hit on a page render. If it's several times, you need to understand why.
  2. Use Debug.Writeline to output relevant information to the output window.
  3. At breakpoints check the call stack to see who's calling what.
  4. Give class instances Guids so you can track if your dealing with the same instance. you can use it in conjuction with Debug.Writeline to output every instantiation of an object.
  5. If you are running any async methods, map out what you think is happening, and then test your model out in debug mode using the methods outlined above.

A misunderstanding of asynchronous code often causes problems such as I think you are eluding to.