Skip to main content

Reducer

Trait Reducer 

Source
pub trait Reducer<StateSlice = ()>:
    Send
    + Sync
    + 'static
where StateSlice: Copy + PartialEq + Eq + Send + Sync + 'static,
{ type State: Clone + Send + Sync + 'static; type Action: Send + 'static; type SideEffect: Send + 'static; // Required methods fn init( &mut self, ctx: InitContext<Self::SideEffect>, ) -> impl Future<Output = ()> + Send; fn reduce( &mut self, state: &mut Self::State, action: Self::Action, ) -> CoreResult<StateChange<StateSlice>>; fn effect( &mut self, state: &mut Self::State, effect: Self::SideEffect, ) -> CoreResult<StateChange<StateSlice>>; // Provided method fn infer_slices( &self, _before: &Self::State, _after: &Self::State, ) -> Vec<StateSlice> { ... } }
Expand description

A reducer defines how actions mutate state and how side-effects are applied.

Implementations are expected to be deterministic with respect to their inputs: given the same state + action/effect, they should produce the same resulting state and StateChange.

Reducers are intentionally split into three phases:

  • Reducer::init: async initialization where the reducer can spawn tasks and retain cloned handles to sideeffect_tx.
  • Reducer::reduce: synchronous state transitions driven by user actions.
  • Reducer::effect: synchronous state transitions driven by background work.

Keeping reduce/effect synchronous makes update ordering easy to reason about (the engine serializes all mutations behind a single mutex), while still enabling async I/O by performing it in spawned tasks and sending the result back as a side-effect.

§Threading

Reducers are used by ReducerEngine. Actions are dispatched serially; you do not need to make your reducer internally thread-safe beyond the trait bounds.

Required Associated Types§

Source

type State: Clone + Send + Sync + 'static

The store state type.

Source

type Action: Send + 'static

The action type consumed by Reducer::reduce.

Source

type SideEffect: Send + 'static

A reducer-defined side-effect type that can be sent to the engine.

Required Methods§

Source

fn init( &mut self, ctx: InitContext<Self::SideEffect>, ) -> impl Future<Output = ()> + Send

Called once when the reducer is installed in an engine.

The provided sender can be used by the reducer to enqueue side-effects (for example, from within Reducer::reduce).

Implementations typically clone ctx.sideeffect_tx and move it into any background tasks the reducer spawns.

Source

fn reduce( &mut self, state: &mut Self::State, action: Self::Action, ) -> CoreResult<StateChange<StateSlice>>

Applies an action to the provided state.

Returning StateChange::Full indicates that a new snapshot should be emitted to subscribers.

Source

fn effect( &mut self, state: &mut Self::State, effect: Self::SideEffect, ) -> CoreResult<StateChange<StateSlice>>

Applies a previously-enqueued side-effect to the provided state.

Side-effects are processed by the engine’s background loop and are intended for work that must be applied out-of-band from normal action dispatch.

Provided Methods§

Source

fn infer_slices( &self, _before: &Self::State, _after: &Self::State, ) -> Vec<StateSlice>

Infers which slices changed between before and after.

This is only used when reducers return StateChange::Infer. Reducers that do not opt into sliced updates can rely on the default empty implementation.

Dyn Compatibility§

This trait is not dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.

Implementors§