Skip to content
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

how to correctly subscribe to an ComputedState<T> state value without inheriting from ComputedStateComponent<T>? #16

Open
neozhu opened this issue May 9, 2024 · 4 comments

Comments

@neozhu
Copy link

neozhu commented May 9, 2024

@alexyakunin

Could you please provide me with an example?

I was trying and failing

public class OnlineUserTracker : IOnlineUserTracker
{

    private readonly ConcurrentDictionary<string, UserInfo> _store = new();
    public async Task AddUser(string sessionId, UserInfo userInfo, CancellationToken cancellationToken = default)
    {
        if (Invalidation.IsActive)
            return;
        if (_store.TryAdd(sessionId, userInfo))
        {
            using var invalidating = Invalidation.Begin();
            _ = await GetOnlineUsers(cancellationToken);
        }
    }
    public async Task UpdateUser(UserInfo userInfo, CancellationToken cancellationToken = default)
    {
        if (Invalidation.IsActive)
            return;
        var invalidate = false;
        foreach (var key in _store.Keys)
        {
            if (_store[key].Id == userInfo.Id)
            {
                var updated = _store.TryUpdate(key, userInfo, _store[key]);
                if (invalidate == false)
                {
                    invalidate = updated;
                }
            }
        }
        if (invalidate)
        {
            using var invalidating = Invalidation.Begin();
            _ = await GetOnlineUsers(cancellationToken);
        }
       

    }
    public virtual Task<UserInfo[]> GetOnlineUsers(CancellationToken cancellationToken = default)
    {
        if (Invalidation.IsActive)
            return default!;
        return Task.FromResult(_store.Select(x => x.Value).Distinct(new UserInfoEqualityComparer()).ToArray());
    }

    public async Task RemoveUser(string sessionId, CancellationToken cancellationToken = default)
    {
        if (Invalidation.IsActive)
            return;
        var removed = _store.TryRemove(sessionId, out var userInfo);
        if (removed)
        {
            using var invalidating = Invalidation.Begin();
            await GetOnlineUsers(cancellationToken);
        }
    }
}
 _computed =await ActualLab.Fusion.Computed.Capture(() => OnlineUserTracker.GetOnlineUsers());
 _computed.Invalidated += StateOnStateChanged;

 private void StateOnStateChanged(ActualLab.Fusion.IComputed v)
 {
     
     InvokeAsync(async() => { StateHasChanged(); 
         _computed.Invalidate();
         _computed = await _computed.Update();
     });
    
 }
@alexyakunin
Copy link
Contributor

@neozhu hi, is this still actual? Are you on Fusion's Discord?

@alexyakunin
Copy link
Contributor

Sorry, I just noticed this issue - just so you know, it's better to notify me on Discord - even if you create an issue here.

@alexyakunin
Copy link
Contributor

Ok, now about your code: the easiest way to achieve what you intend to achieve is: https://github.com/ActualLab/Fusion/blob/master/samples/TodoApp/ConsoleClient/Program.cs#L11C1-L14C2

You can use the same approach with IState as well - i.e. it also has .Changes extension method. I also recommend you to look at the code of this method to learn how it works.

@neozhu
Copy link
Author

neozhu commented Jun 18, 2024

Thank you for your response.
This seems correct, but I found that it doesn't seem to subscribe to data change events.

private Computed<UserInfo[]> computed;
private Action<IComputed> invalidatedHandler;
protected override async Task OnInitializedAsync()
{
  
    computed = await Computed.Capture(() => OnlineUserTracker.GetOnlineUsers());
    invalidatedHandler = async (IComputed c) => await OnInvalidated(c);
    computed.Invalidated += invalidatedHandler;

}
private  async Task OnInvalidated(IComputed state)
{
    await InvokeAsync(StateHasChanged);
}
public void Dispose()
{
    computed.Invalidated -= invalidatedHandler;
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants