与3个子组件共享状态并处理事件助焊剂

时间:2020-06-15 20:05:49

标签: c# blazor flux blazor-webassembly fluxor

我是fluxor及其基础的redux / flux模式的新手。我目前正在从事Blazor wasm项目。 我选择使用fluxor进行状态管理。但我想知道如何处理以下情况:

当页面被加载时,组件1被来自API槽磁通状态管理的数据填充。

组件1是一个列表,其中包含用户可以选择的项目。单击该项目后,应从API中检索该项目,并在组件3的内部完整显示。在组件2中显示表示活动项目的文本。

组件2是一个导航器,它使用简单的后退和下一步按钮进入列表。单击下一步时,组件3应该从API中检索下一个项目并完整显示该项目。然后,组件1通过显示选择列表中的哪一项来反映此更改。

skribbled

我确实有采取行动等方式获得完整物品。我只是不确定从哪里发送它。或者如何确保所有组件都知道活动项是什么。使用“ pure” blazor,我将完成所有低谷事件回调,并在本地处理活动项状态。但这会挫败助焊剂的观点。

1 个答案:

答案 0 :(得分:1)

如果这些组件是单个用例的所有不同部分(以浏览客户端数据),那么我会将它们全部放在一个功能中。

假设您有来自API的以下合同类。

public class ClientSummary
{
  public Guid ID { get; set; }
  public string Name { get; set; }
}

public class ClientDetails
{
  public Guid ID { get; set; }
  public string Name { get; set; }
  public string LotsOfOtherInfo { get; set; }
  public string ArchivedInfo { get; set; }  
}

注意:就我个人而言,我为他们提供了私有的设置器,并使用Newtonsoft来反序列化API响应。这样可以确保它们是不可变的,并且您可以直接在状态中使用它们,而不必创建双类来使您的状态不可变。

您的功能状态可能看起来像这样

public class MyUseCaseState
{
  public bool IsLoadingList { get; }
  public ReadOnlyCollection<ClientSummary> Summaries { get; }
  public int SelectedClientIndex { get; }

  public bool IsLoadingDetails { get; }
  public ClientDetails ClientDetails { get; }

  public MyUseCaseState(
    bool isLoadingList, 
    IEnumerable<ClientSummary> summaries, 
    int selectedClientIndex, 
    bool isLoadingDetails, 
    ClientDetails clientDetails)
  {
    IsLoadingList = isLoadingList;
    Summaries = (summaries ?? Enumerable.Empty<ClientSummary>()).ToList().AsReadOnly();
    SelectedClientIndex = selectedClientIndex;
    IsLoadingDetails = isLoadingDetails;
    ClientDetails = clientDetails;
  }
}

在显示页面时触发的动作不需要任何有效载荷

public class LoadClientListAction {}

reduce会清除列表并将索引设置为-1;

[ReducerMethod]
public static MyUseCaseState ReduceLoadClientListAction(MyUseCaseState state, LoadClientListAction action)
=> new MyUseCaseState(
     isLoadingList: true,
     summaries: null,
     selectedClientIndex: -1,
     isLoadingDetails: false,
     clientDetails: null
   );

您的效果将由服务器获取列表,然后通过操作进入状态

[EffectMethod]
public async Task HandleLoadClientListAction(LoadClientListAction action, IDispatcher dispatcher)
{
  ClientSummary[] clientSummaries = await GetFromApi.....;
  ClientSummary firstClient = clientSummaries.FirstOrDefault();
  var result = new LoadClientListResultAction(clientSummaries, firstClient);
  dispatcher.Dispatch(result);
}

您的减速器方法

[ReducerMethod]
public static MyUseCaseState ReduceLoadClientListResultAction(MyUseCaseState state, LoadClientListResultAction action)
=> new MyUseCaseState(
     isLoadingList: false,
     summaries: action.Summaries,
     selectedClientIndex: action.Summaries.Count == 0 ? -1 : 0,
     isLoadingDetails: false,
     clientDetails: action.FirstClient
   );

现在,每当SelectedClientIndex更改或列表加载时,您都需要为所选客户端加载数据。您只需执行一项操作即可设置选定的索引。

@inject IState<MyUseCaseState> MyUseCaseState

Dispatcher.Dispatcher(new SelectIndexAction(MyUseCaseState.Value.SelectedClientIndex + 1));

您现在可以将IsLoadingDetails设置为true,使用效果从服务器(ClientDetails)获取数据,然后从服务器分派结果以更新您的状态。

[ReducerMethod]
public static MyUseCaseState ReduceSelectIndexAction(MyUseCaseState state, SelectIndexAction action)
=> new MyUseCaseState(
     isLoadingList: state.IsLoadingList,
     summaries: state.Summaries,
     selectedClientIndex: action.SelectedIndex,
     isLoadingDetails: true,
     clientDetails: null
   );

获取数据的效果

[EffectMethod]
public async Task HandleSelectIndexAction(SelectIndexAction action, IDispatcher dispatcher)
{
  ClientDetails details = await GetFromYourApi....
  var result = new SelectIndexResultAction(details);
  dispatcher.Dispatch(result);
}

然后最后更新您的状态

[ReducerMethod]
public static MyUseCaseState ReduceSelectIndexAction(MyUseCaseState state, SelectIndexResultAction action)
=> new MyUseCaseState(
     isLoadingList: state.IsLoadingList,
     summaries: state.Summaries,
     selectedClientIndex: state.SelectedIndex,
     isLoadingDetails: false,
     clientDetails: action.ClientDetails
   );