tui-dispatch 0.6.1

Centralized state management for Rust TUI apps
Documentation

tui-dispatch: Centralized state management for Rust TUI apps

Like Redux/Elm, but for terminals. Components are pure functions of state, and all state mutations happen through dispatched actions.

Quick Start

use tui_dispatch::prelude::*;

// Define your actions
#[derive(Action, Clone, Debug)]
enum MyAction {
    Increment,
    Decrement,
    Quit,
}

// Define your state
#[derive(Default)]
struct MyState {
    count: i32,
}

// Write a reducer
fn reducer(state: &mut MyState, action: MyAction) -> bool {
    match action {
        MyAction::Increment => { state.count += 1; true }
        MyAction::Decrement => { state.count -= 1; true }
        MyAction::Quit => false,
    }
}

// Create a store
let mut store = Store::new(MyState::default(), reducer);
store.dispatch(MyAction::Increment);
assert_eq!(store.state().count, 1);

With Effects

For async operations, use EffectStore with ReducerResult:

use tui_dispatch::prelude::*;

#[derive(Action, Clone, Debug)]
enum Action {
    Fetch,
    DidLoad(String),
}

enum Effect {
    FetchData,
}

#[derive(Default)]
struct State {
    data: Option<String>,
    loading: bool,
}

fn reducer(state: &mut State, action: Action) -> ReducerResult<Effect> {
    match action {
        Action::Fetch => {
            state.loading = true;
            ReducerResult::changed_with(Effect::FetchData)
        }
        Action::DidLoad(data) => {
            state.data = Some(data);
            state.loading = false;
            ReducerResult::changed()
        }
    }
}

let mut store = EffectStore::new(State::default(), reducer);
let result = store.dispatch(Action::Fetch);
assert!(result.changed);
assert_eq!(result.effects.len(), 1);

See the documentation for full guides.