The Effects
What are Effectsβ
Effects are units of logic that run in response to an action, before any associated reducers are invoked.
They are commonly used for:
- Performing side effects (e.g. API calls, logging, validation)
- Dispatching follow-up actions based on results
- Handling asynchronous workflows
π§± Common Pattern: Request + Resultβ
A typical pattern is to define:
SomeAction
β the original triggerSomeActionResult
β dispatched by the effect after the async work is done
Reducers usually handle the Result
action to update the state.
π Naming Conventionβ
Effects are usually named using the actionβs name followed by the Effect
suffix.
Create The Effectβ
internal class IncrementCounterEffect : IEffect<IncrementCounterAction>
{
readonly IStateAccessor<CounterState> _counterState;
public IncrementCounterEffect(IStateAccessor<CounterState> counterState)
{
_counterState = counterState;
}
public async Task EffectAsync(IncrementCounterAction action, IDispatcher dispatcher)
{
// Recommendation: Always Await Dispatch to avoid safe execution issues, it won't block.
await dispatcher.Prepare<IncrementCounterResultAction>()
.With(p => p.Count, _counterState.State.Count + 1)
.DispatchAsync();
}
}
Effects Validatorsβ
Effect validators allow you to run checks before an effect executes, deciding whether the effect should run or be skipped.
They receive both the action and the effect instance, since a single action can trigger multiple effects.
By binding one or more validators to a specific effect, you can control its execution based on any logic you want.
Real-World Scenarioβ
Imagine you have an action, say RequestContentAction
, that is triggered by all users:
- For non-subscribed users, you want an effect that returns a limited preview or redirects to a subscription page.
- For subscribed members, you want a different effect that fetches full content.
Using effect validators, you can bind:
- A validator on the non-member effect that checks if the user is not subscribed and only runs the effect in that case.
- A validator on the member effect that checks if the user is subscribed.
This way, both effects respond to the same action but run conditionally based on user status.
Benefitsβ
- Allows clean separation of logic for different user scenarios
- Keeps action handling unified while supporting multiple conditional outcomes
- Avoids complex branching inside effects themselves
Effect validators are a powerful way to condition effect execution by checking custom conditions involving the action and the current state,
enabling flexible and maintainable multi-effect workflows based on business rules.
if any validator fails the effect is skipped.
internal class IncrementEffectValidator : IEffectValidator<IncrementCounterAction, IncrementCounterEffect>
{
public Task<bool> Validate(IncrementCounterAction action)
{
if (action.Delay > 1000) return Task.FromResult(false);
return Task.FromResult(true);
}
}