与 3 个子组件共享状态和处理事件 |助熔剂
Sharing state and handling events with 3 child components | fluxor
我是 fluxor 及其所基于的 redux/flux 模式的新手。我目前正在从事 Blazor wasm 项目。
我选择使用 fluxor 进行状态管理。但我想知道如何处理以下情况:
当页面加载时,组件 1 会填充来自 API 槽状态管理的数据。
组件 1 是一个包含用户可以 select 的项目的列表。单击时,应从 API 中检索所述项目,并在组件 3 中完整显示。表示活动项目的文本显示在组件 2 中。
组件 2 是一个导航器,它使用简单的后退和下一步按钮浏览列表。单击下一步时,组件 3 应从 API 中检索下一个项目并完整显示该项目。然后,组件 1 通过显示列表中的项目 selected 来反映此更改。
我确实有行动等来获得完整的项目。我只是不确定从哪里发送它。或者如何确保所有组件都知道活动项是什么。使用 "pure" blazor,我会通过事件回调来完成这一切,并在本地处理活动项目状态。但这会破坏 fluxor 的意义。
如果这些组件都是单个用例(浏览客户端数据)的不同部分,那么我会将它们全部放在一个功能中。
假设您有以下合同 类 来自您的 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 {}
reducer 将清除列表并将索引设置为 -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
);
我是 fluxor 及其所基于的 redux/flux 模式的新手。我目前正在从事 Blazor wasm 项目。 我选择使用 fluxor 进行状态管理。但我想知道如何处理以下情况:
当页面加载时,组件 1 会填充来自 API 槽状态管理的数据。
组件 1 是一个包含用户可以 select 的项目的列表。单击时,应从 API 中检索所述项目,并在组件 3 中完整显示。表示活动项目的文本显示在组件 2 中。
组件 2 是一个导航器,它使用简单的后退和下一步按钮浏览列表。单击下一步时,组件 3 应从 API 中检索下一个项目并完整显示该项目。然后,组件 1 通过显示列表中的项目 selected 来反映此更改。
我确实有行动等来获得完整的项目。我只是不确定从哪里发送它。或者如何确保所有组件都知道活动项是什么。使用 "pure" blazor,我会通过事件回调来完成这一切,并在本地处理活动项目状态。但这会破坏 fluxor 的意义。
如果这些组件都是单个用例(浏览客户端数据)的不同部分,那么我会将它们全部放在一个功能中。
假设您有以下合同 类 来自您的 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 {}
reducer 将清除列表并将索引设置为 -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
);