Blazor — Fluxor — состояние не показывает обновление

Я новичок в Blazor и Fluxor. У меня такая проблема: когда я обновляю состояние в одном компоненте, обновленное состояние не отображается в другом компоненте.

На самом деле начальное состояние — это пустой список. Когда я отлаживаю редуктор, состояние обновляется правильно. Я вижу это, когда я меняю состояние во второй раз, я вижу, что состояние заполнено прежним действием. Но в другом компоненте состояние кажется пустым. Я уверен, что что-то пропустил.

Это мой компонент ComboboxFilterOption.razor, состояние которого обновляется:

<div class = "card p-2 @IsFilterActiveCssClass">
    <div class = "row">
        <div class = "col">
            @FilterName
        </div>
    </div>
    <div class = "row">
        <div class = "col">
            <select class = "form-control"
            @onchange = "OnChange"
        >
                <option value = "-1">Please select</option>
                @if (ComboboxItems != null)
                {
                    @foreach (var comboboxItem in ComboboxItems)
                    {
                        <option [email protected]>@comboboxItem.DisplayValue</option>
                    }
                }
            </select>
        </div>
    </div>
    @if (FilterValue != null)
    {
        <div class = "row">
            <div class = "col">
                Selected value: @FilterValue
            </div>
        </div>
    }
</div>

Это файл кода программной части ComboboxFilterOption.razor

using Fluxor;
using GUI.Data;
using GUI.Store.Actions;
using GUI.Store.FilterUseCase;
using Microsoft.AspNetCore.Components;

namespace GUI.Shared.Components.Filter
{
    public partial class ComboboxFilterOption
    {
        [Inject]
        private IState<FilterState> FilterState { get; set; }
        [Inject]
        public IDispatcher Dispatcher { get; set; }


        [Parameter] public string FilterName { get; set; } = string.Empty;
        [Parameter] public string InternalFilterName { get; set; } = string.Empty;
        [Parameter] public List<Data.ComboboxItem>? ComboboxItems { get; set; }

        private Enums.FilterType FilterType = Enums.FilterType.Combobox;
        private string? FilterValue;
        private List<Data.FilterOperator>? FilterOperators = Data.FilterOperator.GetOperatorsForType(Enums.FilterType.Combobox);
        private string IsFilterActiveCssClass = string.Empty;

        private void OnChange(ChangeEventArgs e)
        {
            FilterValue = e.Value?.ToString();
            string newFilterActiveValue = string.Empty;
            if (!string.IsNullOrEmpty(FilterValue) && FilterValue != "-1")
            {
                newFilterActiveValue = "bg-success text-white";
            }
            IsFilterActiveCssClass = newFilterActiveValue;
            Data.Filter updatedFilter = new Data.Filter()
            {
                InternalName = InternalFilterName,
                Type = FilterType,
                Operator = new FilterOperator() { Name = "Equals", Number = 1 },
                Value = FilterValue
            };
            var action = new UpdateFilterAction(updatedFilter);
            Dispatcher.Dispatch(action);
        }
    }
}

Это редуктор FilterState:

using Fluxor;
using GUI.Store.Actions;

namespace GUI.Store.FilterUseCase
{
    public static class Reducers
    {
        [ReducerMethod]
        public static FilterState ReduceUpdateFilterAction(FilterState state, UpdateFilterAction action)
        {
            var alreadySetFilter = state.Filters.Where((filter) => filter.InternalName == action.Filter.InternalName).FirstOrDefault();
            if (alreadySetFilter != null)
            {
                var index = state.Filters.IndexOf(alreadySetFilter);
                state.Filters[index] = action.Filter;
            }
            else
            {
                state.Filters.Add(action.Filter);
            }
            return state;
        }
    }
}

Редьюсер вроде нормально работает, потому что как описано выше он заполняется, когда я вызываю его второй раз. Вот скриншот, где видно, что он заполнен:

Это также отображается в Redux Dev Tools:

Вот код из другого компонента (Filter.razor), где я хочу показать текущий FilterState

@using Fluxor;
@using GUI.Store.Actions;
@using GUI.Store.FilterUseCase;
@inherits Fluxor.Blazor.Web.Components.FluxorComponent

<div class = "container-fluid">
    <div class = "row">
        <div class = "col">
            <GUI.Shared.Components.Filter.ComboboxFilterOption
                InternalFilterName = "ProductStatus"
                FilterName = "Status"
                ComboboxItems=ProductStatus
            />
        </div>
    </div>
    <div>FilterStateCount @FilterState.Value.Filters.Count()</div>
    @foreach (Data.Filter filter in FilterState.Value.Filters)
    {
        <div class = "row">
            <div class = "col">
                @filter.InternalName: @filter.Value
            </div>
        </div>
    }
</div>

@code {
    [Inject]
    private IState<FilterState> FilterState { get; set; }
    [Inject]
    public IDispatcher Dispatcher { get; set; }

    private List<Data.ComboboxItem> ProductStatus = new List<Data.ComboboxItem>()
    {
        new Data.ComboboxItem() { Value = 1, DisplayValue = "DUMMY DATA - INTRO" },
        new Data.ComboboxItem() { Value = 2, DisplayValue = "DUMMY DATA - ACTIVE" },
        new Data.ComboboxItem() { Value = 3, DisplayValue = "DUMMY DATA - DORMANT" },
        new Data.ComboboxItem() { Value = 4, DisplayValue = "DUMMY DATA - STOP FLAGGED" },
    };
}

Я сделал веб-учебник Fluxor — Blazor на https://github.com/mrpmorris/Fluxor/tree/master/Source/Tutorials/02-Blazor/02A-StateActionsReducersTutorial с примером Counter. Этот пример работает нормально! Поэтому я предполагаю, что это не общая проблема интеграции Fluxor.

На самом деле я не понимаю, почему он не показывает текущее состояние.

Для развертывания Сайтов с использованием Blazor, Angular и React с репозиторием на GitHub на Cloudflare
Для развертывания Сайтов с использованием Blazor, Angular и React с репозиторием на GitHub на Cloudflare
Как развернуть сайты с помощью Blazor, Angular и React с репозиторием на GitHub на Cloudflare.
1
0
114
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Я нашел причину. Ошибка была на редукторе. Мне нужно создать новый экземпляр FilterState вместо того, чтобы возвращать и изменять старое обновленное состояние.

До (НЕПРАВИЛЬНО!):

[ReducerMethod]
public static FilterState ReduceUpdateFilterAction(FilterState state, UpdateFilterAction action)
{
    var alreadySetFilter = state.Filters.Where((filter) => filter.InternalName == action.Filter.InternalName).FirstOrDefault();
    if (alreadySetFilter != null)
    {
        var index = state.Filters.IndexOf(alreadySetFilter);
        state.Filters[index] = action.Filter;
    }
    else
    {
        state.Filters.Add(action.Filter);
    }
    return state;
}

ПРАВИЛЬНАЯ/РАБОТАЮЩАЯ версия:

[ReducerMethod]
public static FilterState ReduceUpdateFilterAction(FilterState state, UpdateFilterAction action)
{
    var newList = state.Filters;
    var alreadySetFilter = newList.Where((filter) => filter.InternalName == action.Filter.InternalName).FirstOrDefault();
    if (alreadySetFilter != null)
    {
        var index = newList.IndexOf(alreadySetFilter);
        newList[index] = action.Filter;
    }
    else
    {
        newList.Add(action.Filter);
    }
    return new FilterState(newList);
}

Другие вопросы по теме