skclusive / Skclusive.Mobx.Component

Aspnet core Blazor/Razor component binding for Skclusive.Mobx.Observable
https://skclusive.github.io/Skclusive.Mobx.Component/
MIT License
6 stars 0 forks source link

Not working in latest .NET 5? And question on tracking #3

Open rathga opened 3 years ago

rathga commented 3 years ago

Hi there!

Nice work on this. I'm coming to Blazor from VueJS which has reactivity like this built in, so investigating maybe doing something similar in blazor - and this looks like it is shaping up to something quite close.

I built the project in latest .NET 5 but the observable counter seems not to work as intended: the entire component re-renders (e.g. gets highlighted) instead of just the observable. Is some change needed to PureComponent perhaps?

Secondly, a question on whether tracking would work for nested observables, e.g.

<Observable>
@if (observableBool.Value)
{
  @observableString.Value
}
</Observable>

If observableBool is initially false, but subsequently becomes true, does <Observable> update when observableString changes?

I was going to test this myself but the behaviour doesn't seem to be working at the moment, as per above.

Cheers

skclusive commented 3 years ago

Hi

New update in core.component regressed the demo. updated the demo to work properly.

following was the change made.

[WithDisableBinding(true)] // disables the event handlers implicitly invoking StateHasChanged event for components derived from Skclusive.Core.Component.

builder.Services.TryAddMobxServices(new CoreConfigBuilder().WithDisableBinding(true).Build());

yes. the observability behaviour should work that way only. if not, please report back.

thanks for trying out the project.

cheers

skclusive commented 3 years ago

btw there is Mobx.StateTree port https://github.com/skclusive/Skclusive.Mobx.StateTree and samples using https://github.com/skclusive/Skclusive.Blazor.Samples/tree/master/Skclusive.Blazor.FlightFinder which integrates with Redux dev tool.

rathga commented 3 years ago

Thanks very much - with the disableBinding tweak it is working as expected, and indeed the nested observable also works fine!

From looking at the code, I think this is because you are running tracking on every render? So there is no dep created whilst the bool is false but the dep subsequently gets created after switching to true on the re-render.

This is different (I think) from the observer pattern in VueJS where (for efficiency I presume) the tracking is typically only done on first run, and it has another way to track nested/conditionals observables in templates: Essentially making the user declare all possible observables in the template upfront - which it can do as the framework is also responsible for compiling the template into a render function and therefore can see all possible variables, whereas with Blazor we do not have control of this aspect. So tracking on each render is an interesting alternative.

skclusive commented 3 years ago

Nice that it worked.

Not much idea about VueJs tracking, following the mobx-react-lite binding where component rendering is tracked

https://github.com/mobxjs/mobx-react-lite/blob/master/src/useObserver.ts#L110

reaction.track(() => {
        try {
            rendering = fn()
        } catch (e) {
            exception = e
        }
    })

doing the similar here. i guess it could be optimised if we could retain the behaviour.

https://github.com/skclusive/Skclusive.Mobx.Component/blob/master/src/MobxComponentConfigurer.cs#L24

                reaction.Track(() =>
                {
                    return Actions.AllowStateChanges<object>(false, () =>
                    {
                        renderFragment(builder);

                        return null;
                    });
                });